You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/03/03 03:19:49 UTC

[7/7] incubator-mynewt-newt git commit: MYNEWT-653 Use runtimeco gatt fork.

MYNEWT-653 Use runtimeco gatt fork.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/abf65d3a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/abf65d3a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/abf65d3a

Branch: refs/heads/develop
Commit: abf65d3a748ee8b1078ecd13adef096fb863e413
Parents: 671a154
Author: Christopher Collins <cc...@apache.org>
Authored: Thu Mar 2 19:12:27 2017 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Thu Mar 2 19:18:41 2017 -0800

----------------------------------------------------------------------
 newtmgr/Godeps/Godeps.json                      |  32 +-
 .../vendor/github.com/runtimeco/gatt/.gitignore |   3 +
 .../vendor/github.com/runtimeco/gatt/LICENSE.md |  27 +
 newtmgr/vendor/github.com/runtimeco/gatt/adv.go | 234 +++++
 .../vendor/github.com/runtimeco/gatt/attr.go    | 160 +++
 .../vendor/github.com/runtimeco/gatt/central.go | 152 +++
 .../github.com/runtimeco/gatt/central_darwin.go |  70 ++
 .../github.com/runtimeco/gatt/central_linux.go  | 446 +++++++++
 .../vendor/github.com/runtimeco/gatt/common.go  | 399 ++++++++
 .../vendor/github.com/runtimeco/gatt/const.go   | 153 +++
 .../vendor/github.com/runtimeco/gatt/device.go  | 161 +++
 .../github.com/runtimeco/gatt/device_darwin.go  | 513 ++++++++++
 .../github.com/runtimeco/gatt/device_linux.go   | 240 +++++
 newtmgr/vendor/github.com/runtimeco/gatt/doc.go |  88 ++
 .../github.com/runtimeco/gatt/known_uuid.go     | 122 +++
 .../runtimeco/gatt/l2cap_writer_linux.go        | 156 +++
 .../github.com/runtimeco/gatt/linux/cmd/cmd.go  | 995 +++++++++++++++++++
 .../github.com/runtimeco/gatt/linux/const.go    |  21 +
 .../github.com/runtimeco/gatt/linux/device.go   | 109 ++
 .../github.com/runtimeco/gatt/linux/devices.go  |  58 ++
 .../github.com/runtimeco/gatt/linux/doc.go      |   5 +
 .../github.com/runtimeco/gatt/linux/evt/evt.go  | 382 +++++++
 .../runtimeco/gatt/linux/gioctl/LICENSE.md      |  22 +
 .../runtimeco/gatt/linux/gioctl/README.md       |  12 +
 .../runtimeco/gatt/linux/gioctl/ioctl.go        |  57 ++
 .../github.com/runtimeco/gatt/linux/hci.go      | 400 ++++++++
 .../github.com/runtimeco/gatt/linux/l2cap.go    | 174 ++++
 .../runtimeco/gatt/linux/socket/asm.s           |   8 +
 .../runtimeco/gatt/linux/socket/asm_linux_386.s |  33 +
 .../runtimeco/gatt/linux/socket/socket.go       | 121 +++
 .../gatt/linux/socket/socket_common.go          |  24 +
 .../gatt/linux/socket/socket_darwin.go          |   6 +
 .../runtimeco/gatt/linux/socket/socket_linux.go |   7 +
 .../gatt/linux/socket/socket_linux_386.go       |  31 +
 .../runtimeco/gatt/linux/util/util.go           |  16 +
 .../github.com/runtimeco/gatt/option_darwin.go  |  15 +
 .../github.com/runtimeco/gatt/option_linux.go   |  87 ++
 .../github.com/runtimeco/gatt/peripheral.go     | 102 ++
 .../runtimeco/gatt/peripheral_darwin.go         | 277 ++++++
 .../runtimeco/gatt/peripheral_linux.go          | 448 +++++++++
 .../vendor/github.com/runtimeco/gatt/readme.md  | 115 +++
 .../vendor/github.com/runtimeco/gatt/uuid.go    |  86 ++
 .../github.com/runtimeco/gatt/xpc/LICENSE       |  21 +
 .../vendor/github.com/runtimeco/gatt/xpc/doc.go |   8 +
 .../github.com/runtimeco/gatt/xpc/xpc_darwin.go | 350 +++++++
 .../runtimeco/gatt/xpc/xpc_wrapper_darwin.c     |  85 ++
 .../runtimeco/gatt/xpc/xpc_wrapper_darwin.h     |  32 +
 .../github.com/runtimeinc/gatt/.gitignore       |   3 -
 .../github.com/runtimeinc/gatt/LICENSE.md       |  27 -
 .../vendor/github.com/runtimeinc/gatt/adv.go    | 234 -----
 .../vendor/github.com/runtimeinc/gatt/attr.go   | 160 ---
 .../github.com/runtimeinc/gatt/central.go       | 152 ---
 .../runtimeinc/gatt/central_darwin.go           |  70 --
 .../github.com/runtimeinc/gatt/central_linux.go | 446 ---------
 .../vendor/github.com/runtimeinc/gatt/common.go | 399 --------
 .../vendor/github.com/runtimeinc/gatt/const.go  | 153 ---
 .../vendor/github.com/runtimeinc/gatt/device.go | 161 ---
 .../github.com/runtimeinc/gatt/device_darwin.go | 513 ----------
 .../github.com/runtimeinc/gatt/device_linux.go  | 240 -----
 .../vendor/github.com/runtimeinc/gatt/doc.go    |  88 --
 .../github.com/runtimeinc/gatt/known_uuid.go    | 122 ---
 .../runtimeinc/gatt/l2cap_writer_linux.go       | 156 ---
 .../github.com/runtimeinc/gatt/linux/cmd/cmd.go | 995 -------------------
 .../github.com/runtimeinc/gatt/linux/const.go   |  21 -
 .../github.com/runtimeinc/gatt/linux/device.go  | 109 --
 .../github.com/runtimeinc/gatt/linux/devices.go |  58 --
 .../github.com/runtimeinc/gatt/linux/doc.go     |   5 -
 .../github.com/runtimeinc/gatt/linux/evt/evt.go | 382 -------
 .../runtimeinc/gatt/linux/gioctl/LICENSE.md     |  22 -
 .../runtimeinc/gatt/linux/gioctl/README.md      |  12 -
 .../runtimeinc/gatt/linux/gioctl/ioctl.go       |  57 --
 .../github.com/runtimeinc/gatt/linux/hci.go     | 400 --------
 .../github.com/runtimeinc/gatt/linux/l2cap.go   | 174 ----
 .../runtimeinc/gatt/linux/socket/asm.s          |   8 -
 .../gatt/linux/socket/asm_linux_386.s           |  33 -
 .../runtimeinc/gatt/linux/socket/socket.go      | 121 ---
 .../gatt/linux/socket/socket_common.go          |  24 -
 .../gatt/linux/socket/socket_darwin.go          |   6 -
 .../gatt/linux/socket/socket_linux.go           |   7 -
 .../gatt/linux/socket/socket_linux_386.go       |  31 -
 .../runtimeinc/gatt/linux/util/util.go          |  16 -
 .../github.com/runtimeinc/gatt/option_darwin.go |  15 -
 .../github.com/runtimeinc/gatt/option_linux.go  |  87 --
 .../github.com/runtimeinc/gatt/peripheral.go    | 102 --
 .../runtimeinc/gatt/peripheral_darwin.go        | 277 ------
 .../runtimeinc/gatt/peripheral_linux.go         | 448 ---------
 .../vendor/github.com/runtimeinc/gatt/readme.md | 115 ---
 .../vendor/github.com/runtimeinc/gatt/uuid.go   |  86 --
 .../github.com/runtimeinc/gatt/xpc/LICENSE      |  21 -
 .../github.com/runtimeinc/gatt/xpc/doc.go       |   8 -
 .../runtimeinc/gatt/xpc/xpc_darwin.go           | 350 -------
 .../runtimeinc/gatt/xpc/xpc_wrapper_darwin.c    |  85 --
 .../runtimeinc/gatt/xpc/xpc_wrapper_darwin.h    |  32 -
 93 files changed, 7061 insertions(+), 7033 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/Godeps/Godeps.json
----------------------------------------------------------------------
diff --git a/newtmgr/Godeps/Godeps.json b/newtmgr/Godeps/Godeps.json
index b2571e8..b486ebe 100644
--- a/newtmgr/Godeps/Godeps.json
+++ b/newtmgr/Godeps/Godeps.json
@@ -38,8 +38,8 @@
 			"Rev": "f3009df150dadf309fdee4a54ed65c124afad715"
 		},
 		{
-			"ImportPath": "github.com/runtimeinc/gatt",
-			"Rev": "a8b4c64987af1491ef629e5ec45d3fc47df29eb9"
+			"ImportPath": "github.com/runtimeco/gatt",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
 		},
 		{
 			"ImportPath": "github.com/runtimeinc/gatt/linux",
@@ -116,6 +116,34 @@
 			"ImportPath": "mynewt.apache.org/newt/yaml",
 			"Comment": "pre_sterly_refactor-137-gfcecea4",
 			"Rev": "fcecea4b13ab467168e936a51ef01695833644d8"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux/cmd",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/xpc",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux/evt",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux/gioctl",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux/socket",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
+		},
+		{
+			"ImportPath": "github.com/runtimeco/gatt/linux/util",
+			"Rev": "ceaca1e3d4b698ce4f610b8c71ebc5cde9ad40dd"
 		}
 	]
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/.gitignore
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/.gitignore b/newtmgr/vendor/github.com/runtimeco/gatt/.gitignore
new file mode 100644
index 0000000..7ab0687
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/.gitignore
@@ -0,0 +1,3 @@
+c.out
+c/*-ble
+sample

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/LICENSE.md
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/LICENSE.md b/newtmgr/vendor/github.com/runtimeco/gatt/LICENSE.md
new file mode 100644
index 0000000..51c07a6
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/LICENSE.md
@@ -0,0 +1,27 @@
+Copyright (c) 2014 PayPal Inc. 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 PayPal 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.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/adv.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/adv.go b/newtmgr/vendor/github.com/runtimeco/gatt/adv.go
new file mode 100644
index 0000000..3b8a747
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/adv.go
@@ -0,0 +1,234 @@
+package gatt
+
+import (
+	"errors"
+	"log"
+)
+
+// MaxEIRPacketLength is the maximum allowed AdvertisingPacket
+// and ScanResponsePacket length.
+const MaxEIRPacketLength = 31
+
+// ErrEIRPacketTooLong is the error returned when an AdvertisingPacket
+// or ScanResponsePacket is too long.
+var ErrEIRPacketTooLong = errors.New("max packet length is 31")
+
+// Advertising data field types
+const (
+	typeFlags             = 0x01 // Flags
+	typeSomeUUID16        = 0x02 // Incomplete List of 16-bit Service Class UUIDs
+	typeAllUUID16         = 0x03 // Complete List of 16-bit Service Class UUIDs
+	typeSomeUUID32        = 0x04 // Incomplete List of 32-bit Service Class UUIDs
+	typeAllUUID32         = 0x05 // Complete List of 32-bit Service Class UUIDs
+	typeSomeUUID128       = 0x06 // Incomplete List of 128-bit Service Class UUIDs
+	typeAllUUID128        = 0x07 // Complete List of 128-bit Service Class UUIDs
+	typeShortName         = 0x08 // Shortened Local Name
+	typeCompleteName      = 0x09 // Complete Local Name
+	typeTxPower           = 0x0A // Tx Power Level
+	typeClassOfDevice     = 0x0D // Class of Device
+	typeSimplePairingC192 = 0x0E // Simple Pairing Hash C-192
+	typeSimplePairingR192 = 0x0F // Simple Pairing Randomizer R-192
+	typeSecManagerTK      = 0x10 // Security Manager TK Value
+	typeSecManagerOOB     = 0x11 // Security Manager Out of Band Flags
+	typeSlaveConnInt      = 0x12 // Slave Connection Interval Range
+	typeServiceSol16      = 0x14 // List of 16-bit Service Solicitation UUIDs
+	typeServiceSol128     = 0x15 // List of 128-bit Service Solicitation UUIDs
+	typeServiceData16     = 0x16 // Service Data - 16-bit UUID
+	typePubTargetAddr     = 0x17 // Public Target Address
+	typeRandTargetAddr    = 0x18 // Random Target Address
+	typeAppearance        = 0x19 // Appearance
+	typeAdvInterval       = 0x1A // Advertising Interval
+	typeLEDeviceAddr      = 0x1B // LE Bluetooth Device Address
+	typeLERole            = 0x1C // LE Role
+	typeServiceSol32      = 0x1F // List of 32-bit Service Solicitation UUIDs
+	typeServiceData32     = 0x20 // Service Data - 32-bit UUID
+	typeServiceData128    = 0x21 // Service Data - 128-bit UUID
+	typeLESecConfirm      = 0x22 // LE Secure Connections Confirmation Value
+	typeLESecRandom       = 0x23 // LE Secure Connections Random Value
+	typeManufacturerData  = 0xFF // Manufacturer Specific Data
+)
+
+// Advertising type flags
+const (
+	flagLimitedDiscoverable = 0x01 // LE Limited Discoverable Mode
+	flagGeneralDiscoverable = 0x02 // LE General Discoverable Mode
+	flagLEOnly              = 0x04 // BR/EDR Not Supported. Bit 37 of LMP Feature Mask Definitions (Page 0)
+	flagBothController      = 0x08 // Simultaneous LE and BR/EDR to Same Device Capable (Controller).
+	flagBothHost            = 0x10 // Simultaneous LE and BR/EDR to Same Device Capable (Host).
+)
+
+// FIXME: check the unmarshalling of this data structure.
+type ServiceData struct {
+	UUID UUID
+	Data []byte
+}
+
+// This is borrowed from core bluetooth.
+// Embedded/Linux folks might be interested in more details.
+type Advertisement struct {
+	LocalName        string
+	ManufacturerData []byte
+	ServiceData      []ServiceData
+	Services         []UUID
+	OverflowService  []UUID
+	TxPowerLevel     int
+	Connectable      bool
+	SolicitedService []UUID
+	AddressType uint8
+	Address     [6]byte
+}
+
+// This is only used in Linux port.
+func (a *Advertisement) unmarshall(b []byte) error {
+
+	// Utility function for creating a list of uuids.
+	uuidList := func(u []UUID, d []byte, w int) []UUID {
+		for len(d) > 0 {
+			u = append(u, UUID{d[:w]})
+			d = d[w:]
+		}
+		return u
+	}
+
+	for len(b) > 0 {
+		if len(b) < 2 {
+			return errors.New("invalid advertise data")
+		}
+		l, t := b[0], b[1]
+		if len(b) < int(1+l) {
+			return errors.New("invalid advertise data")
+		}
+		d := b[2 : 1+l]
+		switch t {
+		case typeFlags:
+			// TODO: should we do anything about the discoverability here?
+		case typeSomeUUID16:
+			a.Services = uuidList(a.Services, d, 2)
+		case typeAllUUID16:
+			a.Services = uuidList(a.Services, d, 2)
+		case typeSomeUUID32:
+			a.Services = uuidList(a.Services, d, 4)
+		case typeAllUUID32:
+			a.Services = uuidList(a.Services, d, 4)
+		case typeSomeUUID128:
+			a.Services = uuidList(a.Services, d, 16)
+		case typeAllUUID128:
+			a.Services = uuidList(a.Services, d, 16)
+		case typeShortName:
+			a.LocalName = string(d)
+		case typeCompleteName:
+			a.LocalName = string(d)
+		case typeTxPower:
+			a.TxPowerLevel = int(d[0])
+		case typeServiceSol16:
+			a.SolicitedService = uuidList(a.SolicitedService, d, 2)
+		case typeServiceSol128:
+			a.SolicitedService = uuidList(a.SolicitedService, d, 16)
+		case typeServiceSol32:
+			a.SolicitedService = uuidList(a.SolicitedService, d, 4)
+		case typeManufacturerData:
+			a.ManufacturerData = make([]byte, len(d))
+			copy(a.ManufacturerData, d)
+		// case typeServiceData16,
+		// case typeServiceData32,
+		// case typeServiceData128:
+		default:
+			log.Printf("DATA: [ % X ]", d)
+		}
+		b = b[1+l:]
+	}
+	return nil
+}
+
+// AdvPacket is an utility to help crafting advertisment or scan response data.
+type AdvPacket struct {
+	b []byte
+}
+
+// Bytes returns an 31-byte array, which contains up to 31 bytes of the packet.
+func (a *AdvPacket) Bytes() [31]byte {
+	b := [31]byte{}
+	copy(b[:], a.b)
+	return b
+}
+
+// Len returns the length of the packets with a maximum of 31.
+func (a *AdvPacket) Len() int {
+	if len(a.b) > 31 {
+		return 31
+	}
+	return len(a.b)
+}
+
+// AppendField appends a BLE advertising packet field.
+// TODO: refuse to append field if it'd make the packet too long.
+func (a *AdvPacket) AppendField(typ byte, b []byte) *AdvPacket {
+	// A field consists of len, typ, b.
+	// Len is 1 byte for typ plus len(b).
+	if len(a.b)+2+len(b) > MaxEIRPacketLength {
+		b = b[:MaxEIRPacketLength-len(a.b)-2]
+	}
+	a.b = append(a.b, byte(len(b)+1))
+	a.b = append(a.b, typ)
+	a.b = append(a.b, b...)
+	return a
+}
+
+// AppendFlags appends a flag field to the packet.
+func (a *AdvPacket) AppendFlags(f byte) *AdvPacket {
+	return a.AppendField(typeFlags, []byte{f})
+}
+
+// AppendFlags appends a name field to the packet.
+// If the name fits in the space, it will be append as a complete name field, otherwise a short name field.
+func (a *AdvPacket) AppendName(n string) *AdvPacket {
+	typ := byte(typeCompleteName)
+	if len(a.b)+2+len(n) > MaxEIRPacketLength {
+		typ = byte(typeShortName)
+	}
+	return a.AppendField(typ, []byte(n))
+}
+
+// AppendManufacturerData appends a manufacturer data field to the packet.
+func (a *AdvPacket) AppendManufacturerData(id uint16, b []byte) *AdvPacket {
+	d := append([]byte{uint8(id), uint8(id >> 8)}, b...)
+	return a.AppendField(typeManufacturerData, d)
+}
+
+// AppendUUIDFit appends a BLE advertised service UUID
+// packet field if it fits in the packet, and reports whether the UUID fit.
+func (a *AdvPacket) AppendUUIDFit(uu []UUID) bool {
+	// Iterate all UUIDs to see if they fit in the packet or not.
+	fit, l := true, len(a.b)
+	for _, u := range uu {
+		if u.Equal(attrGAPUUID) || u.Equal(attrGATTUUID) {
+			continue
+		}
+		l += 2 + u.Len()
+		if l > MaxEIRPacketLength {
+			fit = false
+			break
+		}
+	}
+
+	// Append the UUIDs until they no longer fit.
+	for _, u := range uu {
+		if u.Equal(attrGAPUUID) || u.Equal(attrGATTUUID) {
+			continue
+		}
+		if len(a.b)+2+u.Len() > MaxEIRPacketLength {
+			break
+		}
+		switch l = u.Len(); {
+		case l == 2 && fit:
+			a.AppendField(typeAllUUID16, u.b)
+		case l == 16 && fit:
+			a.AppendField(typeAllUUID128, u.b)
+		case l == 2 && !fit:
+			a.AppendField(typeSomeUUID16, u.b)
+		case l == 16 && !fit:
+			a.AppendField(typeSomeUUID128, u.b)
+		}
+	}
+	return fit
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/attr.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/attr.go b/newtmgr/vendor/github.com/runtimeco/gatt/attr.go
new file mode 100644
index 0000000..d1ae09d
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/attr.go
@@ -0,0 +1,160 @@
+package gatt
+
+import "log"
+
+// attr is a BLE attribute. It is not exported;
+// managing attributes is an implementation detail.
+type attr struct {
+	h      uint16   // attribute handle
+	typ    UUID     // attribute type in UUID
+	props  Property // attripute property
+	secure Property // attribute secure (implementation specific usage)
+	value  []byte   // attribute value
+
+	pvt interface{} // point to the corresponsing Serveice/Characteristic/Descriptor
+}
+
+// A attrRange is a contiguous range of attributes.
+type attrRange struct {
+	aa   []attr
+	base uint16 // handle for first attr in aa
+}
+
+const (
+	tooSmall = -1
+	tooLarge = -2
+)
+
+// idx returns the index into aa corresponding to attr a.
+// If h is too small, idx returns tooSmall (-1).
+// If h is too large, idx returns tooLarge (-2).
+func (r *attrRange) idx(h int) int {
+	if h < int(r.base) {
+		return tooSmall
+	}
+	if int(h) >= int(r.base)+len(r.aa) {
+		return tooLarge
+	}
+	return h - int(r.base)
+}
+
+// At returns attr a.
+func (r *attrRange) At(h uint16) (a attr, ok bool) {
+	i := r.idx(int(h))
+	if i < 0 {
+		return attr{}, false
+	}
+	return r.aa[i], true
+}
+
+// Subrange returns attributes in range [start, end]; it may
+// return an empty slice. Subrange does not panic for
+// out-of-range start or end.
+func (r *attrRange) Subrange(start, end uint16) []attr {
+	startidx := r.idx(int(start))
+	switch startidx {
+	case tooSmall:
+		startidx = 0
+	case tooLarge:
+		return []attr{}
+	}
+
+	endidx := r.idx(int(end) + 1) // [start, end] includes its upper bound!
+	switch endidx {
+	case tooSmall:
+		return []attr{}
+	case tooLarge:
+		endidx = len(r.aa)
+	}
+	return r.aa[startidx:endidx]
+}
+
+func dumpAttributes(aa []attr) {
+	log.Printf("Generating attribute table:")
+	log.Printf("handle\ttype\tprops\tsecure\tpvt\tvalue")
+	for _, a := range aa {
+		log.Printf("0x%04X\t0x%s\t0x%02X\t0x%02x\t%T\t[ % X ]",
+			a.h, a.typ, int(a.props), int(a.secure), a.pvt, a.value)
+	}
+}
+
+func generateAttributes(ss []*Service, base uint16) *attrRange {
+	var aa []attr
+	h := base
+	last := len(ss) - 1
+	for i, s := range ss {
+		var a []attr
+		h, a = generateServiceAttributes(s, h, i == last)
+		aa = append(aa, a...)
+	}
+	dumpAttributes(aa)
+	return &attrRange{aa: aa, base: base}
+}
+
+func generateServiceAttributes(s *Service, h uint16, last bool) (uint16, []attr) {
+	s.h = h
+	// endh set later
+	a := attr{
+		h:     h,
+		typ:   attrPrimaryServiceUUID,
+		value: s.uuid.b,
+		props: CharRead,
+		pvt:   s,
+	}
+	aa := []attr{a}
+	h++
+
+	for _, c := range s.Characteristics() {
+		var a []attr
+		h, a = generateCharAttributes(c, h)
+		aa = append(aa, a...)
+	}
+
+	s.endh = h - 1
+	if last {
+		h = 0xFFFF
+		s.endh = h
+	}
+
+	return h, aa
+}
+
+func generateCharAttributes(c *Characteristic, h uint16) (uint16, []attr) {
+	c.h = h
+	c.vh = h + 1
+	ca := attr{
+		h:     c.h,
+		typ:   attrCharacteristicUUID,
+		value: append([]byte{byte(c.props), byte(c.vh), byte((c.vh) >> 8)}, c.uuid.b...),
+		props: c.props,
+		pvt:   c,
+	}
+	va := attr{
+		h:     c.vh,
+		typ:   c.uuid,
+		value: c.value,
+		props: c.props,
+		pvt:   c,
+	}
+	h += 2
+
+	aa := []attr{ca, va}
+	for _, d := range c.descs {
+		aa = append(aa, generateDescAttributes(d, h))
+		h++
+	}
+
+	return h, aa
+}
+
+func generateDescAttributes(d *Descriptor, h uint16) attr {
+	d.h = h
+	a := attr{
+		h:     h,
+		typ:   d.uuid,
+		value: d.value,
+		props: d.props,
+		pvt:   d,
+	}
+	return a
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/central.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/central.go b/newtmgr/vendor/github.com/runtimeco/gatt/central.go
new file mode 100644
index 0000000..55bd2c1
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/central.go
@@ -0,0 +1,152 @@
+package gatt
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"sync"
+)
+
+// Central is the interface that represent a remote central device.
+type Central interface {
+	ID() string   // ID returns platform specific ID of the remote central device.
+	Close() error // Close disconnects the connection.
+	MTU() int     // MTU returns the current connection mtu.
+}
+
+type ResponseWriter interface {
+	// Write writes data to return as the characteristic value.
+	Write([]byte) (int, error)
+
+	// SetStatus reports the result of the read operation. See the Status* constants.
+	SetStatus(byte)
+}
+
+// responseWriter is the default implementation of ResponseWriter.
+type responseWriter struct {
+	capacity int
+	buf      *bytes.Buffer
+	status   byte
+}
+
+func newResponseWriter(c int) *responseWriter {
+	return &responseWriter{
+		capacity: c,
+		buf:      new(bytes.Buffer),
+		status:   StatusSuccess,
+	}
+}
+
+func (w *responseWriter) Write(b []byte) (int, error) {
+	if avail := w.capacity - w.buf.Len(); avail < len(b) {
+		return 0, fmt.Errorf("requested write %d bytes, %d available", len(b), avail)
+	}
+	return w.buf.Write(b)
+}
+
+func (w *responseWriter) SetStatus(status byte) { w.status = status }
+func (w *responseWriter) bytes() []byte         { return w.buf.Bytes() }
+
+// A ReadHandler handles GATT read requests.
+type ReadHandler interface {
+	ServeRead(resp ResponseWriter, req *ReadRequest)
+}
+
+// ReadHandlerFunc is an adapter to allow the use of
+// ordinary functions as ReadHandlers. If f is a function
+// with the appropriate signature, ReadHandlerFunc(f) is a
+// ReadHandler that calls f.
+type ReadHandlerFunc func(resp ResponseWriter, req *ReadRequest)
+
+// ServeRead returns f(r, maxlen, offset).
+func (f ReadHandlerFunc) ServeRead(resp ResponseWriter, req *ReadRequest) {
+	f(resp, req)
+}
+
+// A WriteHandler handles GATT write requests.
+// Write and WriteNR requests are presented identically;
+// the server will ensure that a response is sent if appropriate.
+type WriteHandler interface {
+	ServeWrite(r Request, data []byte) (status byte)
+}
+
+// WriteHandlerFunc is an adapter to allow the use of
+// ordinary functions as WriteHandlers. If f is a function
+// with the appropriate signature, WriteHandlerFunc(f) is a
+// WriteHandler that calls f.
+type WriteHandlerFunc func(r Request, data []byte) byte
+
+// ServeWrite returns f(r, data).
+func (f WriteHandlerFunc) ServeWrite(r Request, data []byte) byte {
+	return f(r, data)
+}
+
+// A NotifyHandler handles GATT notification requests.
+// Notifications can be sent using the provided notifier.
+type NotifyHandler interface {
+	ServeNotify(r Request, n Notifier)
+}
+
+// NotifyHandlerFunc is an adapter to allow the use of
+// ordinary functions as NotifyHandlers. If f is a function
+// with the appropriate signature, NotifyHandlerFunc(f) is a
+// NotifyHandler that calls f.
+type NotifyHandlerFunc func(r Request, n Notifier)
+
+// ServeNotify calls f(r, n).
+func (f NotifyHandlerFunc) ServeNotify(r Request, n Notifier) {
+	f(r, n)
+}
+
+// A Notifier provides a means for a GATT server to send
+// notifications about value changes to a connected device.
+// Notifiers are provided by NotifyHandlers.
+type Notifier interface {
+	// Write sends data to the central.
+	Write(data []byte) (int, error)
+
+	// Done reports whether the central has requested not to
+	// receive any more notifications with this notifier.
+	Done() bool
+
+	// Cap returns the maximum number of bytes that may be sent
+	// in a single notification.
+	Cap() int
+}
+
+type notifier struct {
+	central *central
+	a       *attr
+	maxlen  int
+	donemu  sync.RWMutex
+	done    bool
+}
+
+func newNotifier(c *central, a *attr, maxlen int) *notifier {
+	return &notifier{central: c, a: a, maxlen: maxlen}
+}
+
+func (n *notifier) Write(b []byte) (int, error) {
+	n.donemu.RLock()
+	defer n.donemu.RUnlock()
+	if n.done {
+		return 0, errors.New("central stopped notifications")
+	}
+	return n.central.sendNotification(n.a, b)
+}
+
+func (n *notifier) Cap() int {
+	return n.maxlen
+}
+
+func (n *notifier) Done() bool {
+	n.donemu.RLock()
+	defer n.donemu.RUnlock()
+	return n.done
+}
+
+func (n *notifier) stop() {
+	n.donemu.Lock()
+	n.done = true
+	n.donemu.Unlock()
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/central_darwin.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/central_darwin.go b/newtmgr/vendor/github.com/runtimeco/gatt/central_darwin.go
new file mode 100644
index 0000000..47faa2e
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/central_darwin.go
@@ -0,0 +1,70 @@
+package gatt
+
+import (
+	"sync"
+
+	"github.com/runtimeco/gatt/xpc"
+)
+
+type central struct {
+	dev         *device
+	uuid        UUID
+	mtu         int
+	notifiers   map[uint16]*notifier
+	notifiersmu *sync.Mutex
+}
+
+func newCentral(d *device, u UUID) *central {
+	return &central{
+		dev:         d,
+		mtu:         23,
+		uuid:        u,
+		notifiers:   make(map[uint16]*notifier),
+		notifiersmu: &sync.Mutex{},
+	}
+}
+
+func (c *central) ID() string   { return c.uuid.String() }
+func (c *central) Close() error { return nil }
+func (c *central) MTU() int     { return c.mtu }
+
+func (c *central) sendNotification(a *attr, b []byte) (int, error) {
+	data := make([]byte, len(b))
+	copy(data, b) // have to make a copy, why?
+	c.dev.sendCmd(15, xpc.Dict{
+		// "kCBMsgArgUUIDs": [][]byte{reverse(c.uuid.b)}, // connection interrupted
+		// "kCBMsgArgUUIDs": [][]byte{c.uuid.b}, // connection interrupted
+		// "kCBMsgArgUUIDs": []xpc.UUID{xpc.UUID(reverse(c.uuid.b))},
+		// "kCBMsgArgUUIDs": []xpc.UUID{xpc.UUID(c.uuid.b)},
+		// "kCBMsgArgUUIDs": reverse(c.uuid.b),
+		//
+		// FIXME: Sigh... tried to targeting the central, but couldn't get work.
+		// So, broadcast to all subscribed centrals. Either of the following works.
+		// "kCBMsgArgUUIDs": []xpc.UUID{},
+		"kCBMsgArgUUIDs":       [][]byte{},
+		"kCBMsgArgAttributeID": a.h,
+		"kCBMsgArgData":        data,
+	})
+	return len(b), nil
+}
+
+func (c *central) startNotify(a *attr, maxlen int) {
+	c.notifiersmu.Lock()
+	defer c.notifiersmu.Unlock()
+	if _, found := c.notifiers[a.h]; found {
+		return
+	}
+	n := newNotifier(c, a, maxlen)
+	c.notifiers[a.h] = n
+	char := a.pvt.(*Characteristic)
+	go char.nhandler.ServeNotify(Request{Central: c}, n)
+}
+
+func (c *central) stopNotify(a *attr) {
+	c.notifiersmu.Lock()
+	defer c.notifiersmu.Unlock()
+	if n, found := c.notifiers[a.h]; found {
+		n.stop()
+		delete(c.notifiers, a.h)
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/central_linux.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/central_linux.go b/newtmgr/vendor/github.com/runtimeco/gatt/central_linux.go
new file mode 100644
index 0000000..3ae6994
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/central_linux.go
@@ -0,0 +1,446 @@
+package gatt
+
+import (
+	"encoding/binary"
+	"io"
+	"net"
+	"sync"
+)
+
+type security int
+
+const (
+	securityLow = iota
+	securityMed
+	securityHigh
+)
+
+type central struct {
+	attrs       *attrRange
+	mtu         uint16
+	addr        net.HardwareAddr
+	security    security
+	l2conn      io.ReadWriteCloser
+	notifiers   map[uint16]*notifier
+	notifiersmu *sync.Mutex
+}
+
+func newCentral(a *attrRange, addr net.HardwareAddr, l2conn io.ReadWriteCloser) *central {
+	return &central{
+		attrs:       a,
+		mtu:         23,
+		addr:        addr,
+		security:    securityLow,
+		l2conn:      l2conn,
+		notifiers:   make(map[uint16]*notifier),
+		notifiersmu: &sync.Mutex{},
+	}
+}
+
+func (c *central) ID() string {
+	return c.addr.String()
+}
+
+func (c *central) Close() error {
+	c.notifiersmu.Lock()
+	defer c.notifiersmu.Unlock()
+	for _, n := range c.notifiers {
+		n.stop()
+	}
+	return c.l2conn.Close()
+}
+
+func (c *central) MTU() int {
+	return int(c.mtu)
+}
+
+func (c *central) loop() {
+	for {
+		// L2CAP implementations shall support a minimum MTU size of 48 bytes.
+		// The default value is 672 bytes
+		b := make([]byte, 672)
+		n, err := c.l2conn.Read(b)
+		if n == 0 || err != nil {
+			c.Close()
+			break
+		}
+		if rsp := c.handleReq(b[:n]); rsp != nil {
+			c.l2conn.Write(rsp)
+		}
+	}
+}
+
+// handleReq dispatches a raw request from the central shim
+// to an appropriate handler, based on its type.
+// It panics if len(b) == 0.
+func (c *central) handleReq(b []byte) []byte {
+	var resp []byte
+	switch reqType, req := b[0], b[1:]; reqType {
+	case attOpMtuReq:
+		resp = c.handleMTU(req)
+	case attOpFindInfoReq:
+		resp = c.handleFindInfo(req)
+	case attOpFindByTypeValueReq:
+		resp = c.handleFindByTypeValue(req)
+	case attOpReadByTypeReq:
+		resp = c.handleReadByType(req)
+	case attOpReadReq:
+		resp = c.handleRead(req)
+	case attOpReadBlobReq:
+		resp = c.handleReadBlob(req)
+	case attOpReadByGroupReq:
+		resp = c.handleReadByGroup(req)
+	case attOpWriteReq, attOpWriteCmd:
+		resp = c.handleWrite(reqType, req)
+	case attOpReadMultiReq, attOpPrepWriteReq, attOpExecWriteReq, attOpSignedWriteCmd:
+		fallthrough
+	default:
+		resp = attErrorRsp(reqType, 0x0000, attEcodeReqNotSupp)
+	}
+	return resp
+}
+
+func (c *central) handleMTU(b []byte) []byte {
+	c.mtu = binary.LittleEndian.Uint16(b[:2])
+	if c.mtu < 23 {
+		c.mtu = 23
+	}
+	if c.mtu >= 256 {
+		c.mtu = 256
+	}
+	return []byte{attOpMtuRsp, uint8(c.mtu), uint8(c.mtu >> 8)}
+}
+
+// REQ: FindInfoReq(0x04), StartHandle, EndHandle
+// RSP: FindInfoRsp(0x05), UUIDFormat, Handle, UUID, Handle, UUID, ...
+func (c *central) handleFindInfo(b []byte) []byte {
+	start, end := readHandleRange(b[:4])
+
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpFindInfoRsp)
+
+	uuidLen := -1
+	for _, a := range c.attrs.Subrange(start, end) {
+		if uuidLen == -1 {
+			uuidLen = a.typ.Len()
+			if uuidLen == 2 {
+				w.WriteByteFit(0x01) // TODO: constants for 16bit vs 128bit uuid magic numbers here
+			} else {
+				w.WriteByteFit(0x02)
+			}
+		}
+		if a.typ.Len() != uuidLen {
+			break
+		}
+		w.Chunk()
+		w.WriteUint16Fit(a.h)
+		w.WriteUUIDFit(a.typ)
+		if ok := w.Commit(); !ok {
+			break
+		}
+	}
+
+	if uuidLen == -1 {
+		return attErrorRsp(attOpFindInfoReq, start, attEcodeAttrNotFound)
+	}
+	return w.Bytes()
+}
+
+// REQ: FindByTypeValueReq(0x06), StartHandle, EndHandle, Type(UUID), Value
+// RSP: FindByTypeValueRsp(0x07), AttrHandle, GroupEndHandle, AttrHandle, GroupEndHandle, ...
+func (c *central) handleFindByTypeValue(b []byte) []byte {
+	start, end := readHandleRange(b[:4])
+	t := UUID{b[4:6]}
+	u := UUID{b[6:]}
+
+	// Only support the ATT ReadByGroupReq for GATT Primary Service Discovery.
+	// More sepcifically, the "Discover Primary Services By Service UUID" sub-procedure
+	if !t.Equal(attrPrimaryServiceUUID) {
+		return attErrorRsp(attOpFindByTypeValueReq, start, attEcodeAttrNotFound)
+	}
+
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpFindByTypeValueRsp)
+
+	var wrote bool
+	for _, a := range c.attrs.Subrange(start, end) {
+		if !a.typ.Equal(attrPrimaryServiceUUID) {
+			continue
+		}
+		if !(UUID{a.value}.Equal(u)) {
+			continue
+		}
+		s := a.pvt.(*Service)
+		w.Chunk()
+		w.WriteUint16Fit(s.h)
+		w.WriteUint16Fit(s.endh)
+		if ok := w.Commit(); !ok {
+			break
+		}
+		wrote = true
+	}
+	if !wrote {
+		return attErrorRsp(attOpFindByTypeValueReq, start, attEcodeAttrNotFound)
+	}
+
+	return w.Bytes()
+}
+
+// REQ: ReadByType(0x08), StartHandle, EndHandle, Type(UUID)
+// RSP: ReadByType(0x09), LenOfEachDataField, DataField, DataField, ...
+func (c *central) handleReadByType(b []byte) []byte {
+	start, end := readHandleRange(b[:4])
+	t := UUID{b[4:]}
+
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpReadByTypeRsp)
+	uuidLen := -1
+	for _, a := range c.attrs.Subrange(start, end) {
+		if !a.typ.Equal(t) {
+			continue
+		}
+		if (a.secure&CharRead) != 0 && c.security > securityLow {
+			return attErrorRsp(attOpReadByTypeReq, start, attEcodeAuthentication)
+		}
+		v := a.value
+		if v == nil {
+			rsp := newResponseWriter(int(c.mtu - 1))
+			req := &ReadRequest{
+				Request: Request{Central: c},
+				Cap:     int(c.mtu - 1),
+				Offset:  0,
+			}
+			if c, ok := a.pvt.(*Characteristic); ok {
+				c.rhandler.ServeRead(rsp, req)
+			} else if d, ok := a.pvt.(*Descriptor); ok {
+				d.rhandler.ServeRead(rsp, req)
+			}
+			v = rsp.bytes()
+		}
+		if uuidLen == -1 {
+			uuidLen = len(v)
+			w.WriteByteFit(byte(uuidLen) + 2)
+		}
+		if len(v) != uuidLen {
+			break
+		}
+		w.Chunk()
+		w.WriteUint16Fit(a.h)
+		w.WriteFit(v)
+		if ok := w.Commit(); !ok {
+			break
+		}
+	}
+	if uuidLen == -1 {
+		return attErrorRsp(attOpReadByTypeReq, start, attEcodeAttrNotFound)
+	}
+	return w.Bytes()
+}
+
+// REQ: ReadReq(0x0A), Handle
+// RSP: ReadRsp(0x0B), Value
+func (c *central) handleRead(b []byte) []byte {
+	h := binary.LittleEndian.Uint16(b)
+	a, ok := c.attrs.At(h)
+	if !ok {
+		return attErrorRsp(attOpReadReq, h, attEcodeInvalidHandle)
+	}
+	if a.props&CharRead == 0 {
+		return attErrorRsp(attOpReadReq, h, attEcodeReadNotPerm)
+	}
+	if a.secure&CharRead != 0 && c.security > securityLow {
+		return attErrorRsp(attOpReadReq, h, attEcodeAuthentication)
+	}
+	v := a.value
+	if v == nil {
+		req := &ReadRequest{
+			Request: Request{Central: c},
+			Cap:     int(c.mtu - 1),
+			Offset:  0,
+		}
+		rsp := newResponseWriter(int(c.mtu - 1))
+		if c, ok := a.pvt.(*Characteristic); ok {
+			c.rhandler.ServeRead(rsp, req)
+		} else if d, ok := a.pvt.(*Descriptor); ok {
+			d.rhandler.ServeRead(rsp, req)
+		}
+		v = rsp.bytes()
+	}
+
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpReadRsp)
+	w.Chunk()
+	w.WriteFit(v)
+	w.CommitFit()
+	return w.Bytes()
+}
+
+// FIXME: check this, untested, might be broken
+func (c *central) handleReadBlob(b []byte) []byte {
+	h := binary.LittleEndian.Uint16(b)
+	offset := binary.LittleEndian.Uint16(b[2:])
+	a, ok := c.attrs.At(h)
+	if !ok {
+		return attErrorRsp(attOpReadBlobReq, h, attEcodeInvalidHandle)
+	}
+	if a.props&CharRead == 0 {
+		return attErrorRsp(attOpReadBlobReq, h, attEcodeReadNotPerm)
+	}
+	if a.secure&CharRead != 0 && c.security > securityLow {
+		return attErrorRsp(attOpReadBlobReq, h, attEcodeAuthentication)
+	}
+	v := a.value
+	if v == nil {
+		req := &ReadRequest{
+			Request: Request{Central: c},
+			Cap:     int(c.mtu - 1),
+			Offset:  int(offset),
+		}
+		rsp := newResponseWriter(int(c.mtu - 1))
+		if c, ok := a.pvt.(*Characteristic); ok {
+			c.rhandler.ServeRead(rsp, req)
+		} else if d, ok := a.pvt.(*Descriptor); ok {
+			d.rhandler.ServeRead(rsp, req)
+		}
+		v = rsp.bytes()
+		offset = 0 // the server has already adjusted for the offset
+	}
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpReadBlobRsp)
+	w.Chunk()
+	w.WriteFit(v)
+	if ok := w.ChunkSeek(offset); !ok {
+		return attErrorRsp(attOpReadBlobReq, h, attEcodeInvalidOffset)
+	}
+	w.CommitFit()
+	return w.Bytes()
+}
+
+func (c *central) handleReadByGroup(b []byte) []byte {
+	start, end := readHandleRange(b)
+	t := UUID{b[4:]}
+
+	// Only support the ATT ReadByGroupReq for GATT Primary Service Discovery.
+	// More specifically, the "Discover All Primary Services" sub-procedure.
+	if !t.Equal(attrPrimaryServiceUUID) {
+		return attErrorRsp(attOpReadByGroupReq, start, attEcodeUnsuppGrpType)
+	}
+
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpReadByGroupRsp)
+	uuidLen := -1
+	for _, a := range c.attrs.Subrange(start, end) {
+		if !a.typ.Equal(attrPrimaryServiceUUID) {
+			continue
+		}
+		if uuidLen == -1 {
+			uuidLen = len(a.value)
+			w.WriteByteFit(byte(uuidLen + 4))
+		}
+		if uuidLen != len(a.value) {
+			break
+		}
+		s := a.pvt.(*Service)
+		w.Chunk()
+		w.WriteUint16Fit(s.h)
+		w.WriteUint16Fit(s.endh)
+		w.WriteFit(a.value)
+		if ok := w.Commit(); !ok {
+			break
+		}
+	}
+	if uuidLen == -1 {
+		return attErrorRsp(attOpReadByGroupReq, start, attEcodeAttrNotFound)
+	}
+	return w.Bytes()
+}
+
+func (c *central) handleWrite(reqType byte, b []byte) []byte {
+	h := binary.LittleEndian.Uint16(b[:2])
+	value := b[2:]
+
+	a, ok := c.attrs.At(h)
+	if !ok {
+		return attErrorRsp(reqType, h, attEcodeInvalidHandle)
+	}
+
+	noRsp := reqType == attOpWriteCmd
+	charFlag := CharWrite
+	if noRsp {
+		charFlag = CharWriteNR
+	}
+	if a.props&charFlag == 0 {
+		return attErrorRsp(reqType, h, attEcodeWriteNotPerm)
+	}
+	if a.secure&charFlag == 0 && c.security > securityLow {
+		return attErrorRsp(reqType, h, attEcodeAuthentication)
+	}
+
+	// Props of Service and Characteristic declration are read only.
+	// So we only need deal with writable descriptors here.
+	// (Characteristic's value is implemented with descriptor)
+	if !a.typ.Equal(attrClientCharacteristicConfigUUID) {
+		// Regular write, not CCC
+		r := Request{Central: c}
+		if c, ok := a.pvt.(*Characteristic); ok {
+			c.whandler.ServeWrite(r, value)
+		} else if d, ok := a.pvt.(*Characteristic); ok {
+			d.whandler.ServeWrite(r, value)
+		}
+		if noRsp {
+			return nil
+		} else {
+			return []byte{attOpWriteRsp}
+		}
+	}
+
+	// CCC/descriptor write
+	if len(value) != 2 {
+		return attErrorRsp(reqType, h, attEcodeInvalAttrValueLen)
+	}
+	ccc := binary.LittleEndian.Uint16(value)
+	// char := a.pvt.(*Descriptor).char
+	if ccc&(gattCCCNotifyFlag|gattCCCIndicateFlag) != 0 {
+		c.startNotify(&a, int(c.mtu-3))
+	} else {
+		c.stopNotify(&a)
+	}
+	if noRsp {
+		return nil
+	}
+	return []byte{attOpWriteRsp}
+}
+
+func (c *central) sendNotification(a *attr, data []byte) (int, error) {
+	w := newL2capWriter(c.mtu)
+	w.WriteByteFit(attOpHandleNotify)
+	w.WriteUint16Fit(a.pvt.(*Descriptor).char.vh)
+	w.WriteFit(data)
+	return c.l2conn.Write(w.Bytes())
+}
+
+func readHandleRange(b []byte) (start, end uint16) {
+	return binary.LittleEndian.Uint16(b), binary.LittleEndian.Uint16(b[2:])
+}
+
+func (c *central) startNotify(a *attr, maxlen int) {
+	c.notifiersmu.Lock()
+	defer c.notifiersmu.Unlock()
+	if _, found := c.notifiers[a.h]; found {
+		return
+	}
+	char := a.pvt.(*Descriptor).char
+	n := newNotifier(c, a, maxlen)
+	c.notifiers[a.h] = n
+	go char.nhandler.ServeNotify(Request{Central: c}, n)
+}
+
+func (c *central) stopNotify(a *attr) {
+	c.notifiersmu.Lock()
+	defer c.notifiersmu.Unlock()
+	// char := a.pvt.(*Characteristic)
+	if n, found := c.notifiers[a.h]; found {
+		n.stop()
+		delete(c.notifiers, a.h)
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/common.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/common.go b/newtmgr/vendor/github.com/runtimeco/gatt/common.go
new file mode 100644
index 0000000..4fa2389
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/common.go
@@ -0,0 +1,399 @@
+package gatt
+
+// Supported statuses for GATT characteristic read/write operations.
+// These correspond to att constants in the BLE spec
+const (
+	StatusSuccess         = 0
+	StatusInvalidOffset   = 1
+	StatusUnexpectedError = 2
+)
+
+// A Request is the context for a request from a connected central device.
+// TODO: Replace this with more general context, such as:
+// http://godoc.org/golang.org/x/net/context
+type Request struct {
+	Central Central
+}
+
+// A ReadRequest is a characteristic read request from a connected device.
+type ReadRequest struct {
+	Request
+	Cap    int // maximum allowed reply length
+	Offset int // request value offset
+}
+
+type Property int
+
+// Characteristic property flags (spec 3.3.3.1)
+const (
+	CharBroadcast   Property = 0x01 // may be brocasted
+	CharRead        Property = 0x02 // may be read
+	CharWriteNR     Property = 0x04 // may be written to, with no reply
+	CharWrite       Property = 0x08 // may be written to, with a reply
+	CharNotify      Property = 0x10 // supports notifications
+	CharIndicate    Property = 0x20 // supports Indications
+	CharSignedWrite Property = 0x40 // supports signed write
+	CharExtended    Property = 0x80 // supports extended properties
+)
+
+func (p Property) String() (result string) {
+	if (p & CharBroadcast) != 0 {
+		result += "broadcast "
+	}
+	if (p & CharRead) != 0 {
+		result += "read "
+	}
+	if (p & CharWriteNR) != 0 {
+		result += "writeWithoutResponse "
+	}
+	if (p & CharWrite) != 0 {
+		result += "write "
+	}
+	if (p & CharNotify) != 0 {
+		result += "notify "
+	}
+	if (p & CharIndicate) != 0 {
+		result += "indicate "
+	}
+	if (p & CharSignedWrite) != 0 {
+		result += "authenticateSignedWrites "
+	}
+	if (p & CharExtended) != 0 {
+		result += "extendedProperties "
+	}
+	return
+}
+
+// A Service is a BLE service.
+type Service struct {
+	uuid  UUID
+	chars []*Characteristic
+
+	h    uint16
+	endh uint16
+}
+
+// NewService creates and initialize a new Service using u as it's UUID.
+func NewService(u UUID) *Service {
+	return &Service{uuid: u}
+}
+
+// AddCharacteristic adds a characteristic to a service.
+// AddCharacteristic panics if the service already contains another
+// characteristic with the same UUID.
+func (s *Service) AddCharacteristic(u UUID) *Characteristic {
+	for _, c := range s.chars {
+		if c.uuid.Equal(u) {
+			panic("service already contains a characteristic with uuid " + u.String())
+		}
+	}
+	c := &Characteristic{uuid: u, svc: s}
+	s.chars = append(s.chars, c)
+	return c
+}
+
+// UUID returns the UUID of the service.
+func (s *Service) UUID() UUID { return s.uuid }
+
+// Name returns the specificatin name of the service according to its UUID.
+// If the UUID is not assigne, Name returns an empty string.
+func (s *Service) Name() string {
+	return knownServices[s.uuid.String()].Name
+}
+
+// Handle returns the Handle of the service.
+func (s *Service) Handle() uint16 { return s.h }
+
+// EndHandle returns the End Handle of the service.
+func (s *Service) EndHandle() uint16 { return s.endh }
+
+// SetHandle sets the Handle of the service.
+func (s *Service) SetHandle(h uint16) { s.h = h }
+
+// SetEndHandle sets the End Handle of the service.
+func (s *Service) SetEndHandle(endh uint16) { s.endh = endh }
+
+// SetCharacteristics sets the Characteristics of the service.
+func (s *Service) SetCharacteristics(chars []*Characteristic) { s.chars = chars }
+
+// Characteristic returns the contained characteristic of this service.
+func (s *Service) Characteristics() []*Characteristic { return s.chars }
+
+// A Characteristic is a BLE characteristic.
+type Characteristic struct {
+	uuid   UUID
+	props  Property // enabled properties
+	secure Property // security enabled properties
+	svc    *Service
+	cccd   *Descriptor
+	descs  []*Descriptor
+
+	value []byte
+
+	// All the following fields are only used in peripheral/server implementation.
+	rhandler ReadHandler
+	whandler WriteHandler
+	nhandler NotifyHandler
+
+	h    uint16
+	vh   uint16
+	endh uint16
+}
+
+// NewCharacteristic creates and returns a Characteristic.
+func NewCharacteristic(u UUID, s *Service, props Property, h uint16, vh uint16) *Characteristic {
+	c := &Characteristic{
+		uuid:  u,
+		svc:   s,
+		props: props,
+		h:     h,
+		vh:    vh,
+	}
+
+	return c
+}
+
+// Handle returns the Handle of the characteristic.
+func (c *Characteristic) Handle() uint16 { return c.h }
+
+// VHandle returns the Value Handle of the characteristic.
+func (c *Characteristic) VHandle() uint16 { return c.vh }
+
+// EndHandle returns the End Handle of the characteristic.
+func (c *Characteristic) EndHandle() uint16 { return c.endh }
+
+// Descriptor returns the Descriptor of the characteristic.
+func (c *Characteristic) Descriptor() *Descriptor { return c.cccd }
+
+// SetHandle sets the Handle of the characteristic.
+func (c *Characteristic) SetHandle(h uint16) { c.h = h }
+
+// SetVHandle sets the Value Handle of the characteristic.
+func (c *Characteristic) SetVHandle(vh uint16) { c.vh = vh }
+
+// SetEndHandle sets the End Handle of the characteristic.
+func (c *Characteristic) SetEndHandle(endh uint16) { c.endh = endh }
+
+// SetDescriptor sets the Descriptor of the characteristic.
+func (c *Characteristic) SetDescriptor(cccd *Descriptor) { c.cccd = cccd }
+
+// SetDescriptors sets the list of Descriptor of the characteristic.
+func (c *Characteristic) SetDescriptors(descs []*Descriptor) { c.descs = descs }
+
+// UUID returns the UUID of the characteristic.
+func (c *Characteristic) UUID() UUID {
+	return c.uuid
+}
+
+// Name returns the specificatin name of the characteristic.
+// If the UUID is not assigned, Name returns empty string.
+func (c *Characteristic) Name() string {
+	return knownCharacteristics[c.uuid.String()].Name
+}
+
+// Service returns the containing service of this characteristic.
+func (c *Characteristic) Service() *Service {
+	return c.svc
+}
+
+// Properties returns the properties of this characteristic.
+func (c *Characteristic) Properties() Property {
+	return c.props
+}
+
+// Descriptors returns the contained descriptors of this characteristic.
+func (c *Characteristic) Descriptors() []*Descriptor {
+	return c.descs
+}
+
+// AddDescriptor adds a descriptor to a characteristic.
+// AddDescriptor panics if the characteristic already contains another
+// descriptor with the same UUID.
+func (c *Characteristic) AddDescriptor(u UUID) *Descriptor {
+	for _, d := range c.descs {
+		if d.uuid.Equal(u) {
+			panic("service already contains a characteristic with uuid " + u.String())
+		}
+	}
+	d := &Descriptor{uuid: u, char: c}
+	c.descs = append(c.descs, d)
+	return d
+}
+
+// SetValue makes the characteristic support read requests, and returns a
+// static value. SetValue must be called before the containing service is
+// added to a server.
+// SetValue panics if the characteristic has been configured with a ReadHandler.
+func (c *Characteristic) SetValue(b []byte) {
+	if c.rhandler != nil {
+		panic("charactristic has been configured with a read handler")
+	}
+	c.props |= CharRead
+	// c.secure |= CharRead
+	c.value = make([]byte, len(b))
+	copy(c.value, b)
+}
+
+// HandleRead makes the characteristic support read requests, and routes read
+// requests to h. HandleRead must be called before the containing service is
+// added to a server.
+// HandleRead panics if the characteristic has been configured with a static value.
+func (c *Characteristic) HandleRead(h ReadHandler) {
+	if c.value != nil {
+		panic("charactristic has been configured with a static value")
+	}
+	c.props |= CharRead
+	// c.secure |= CharRead
+	c.rhandler = h
+}
+
+// HandleReadFunc calls HandleRead(ReadHandlerFunc(f)).
+func (c *Characteristic) HandleReadFunc(f func(rsp ResponseWriter, req *ReadRequest)) {
+	c.HandleRead(ReadHandlerFunc(f))
+}
+
+// HandleWrite makes the characteristic support write and write-no-response
+// requests, and routes write requests to h.
+// The WriteHandler does not differentiate between write and write-no-response
+// requests; it is handled automatically.
+// HandleWrite must be called before the containing service is added to a server.
+func (c *Characteristic) HandleWrite(h WriteHandler) {
+	c.props |= CharWrite | CharWriteNR
+	// c.secure |= CharWrite | CharWriteNR
+	c.whandler = h
+}
+
+// HandleWriteFunc calls HandleWrite(WriteHandlerFunc(f)).
+func (c *Characteristic) HandleWriteFunc(f func(r Request, data []byte) (status byte)) {
+	c.HandleWrite(WriteHandlerFunc(f))
+}
+
+// HandleNotify makes the characteristic support notify requests, and routes
+// notification requests to h. HandleNotify must be called before the
+// containing service is added to a server.
+func (c *Characteristic) HandleNotify(h NotifyHandler) {
+	if c.cccd != nil {
+		return
+	}
+	p := CharNotify | CharIndicate
+	c.props |= p
+	c.nhandler = h
+
+	// add ccc (client characteristic configuration) descriptor
+	secure := Property(0)
+	// If the characteristic requested secure notifications,
+	// then set ccc security to r/w.
+	if c.secure&p != 0 {
+		secure = CharRead | CharWrite
+	}
+	cd := &Descriptor{
+		uuid:   attrClientCharacteristicConfigUUID,
+		props:  CharRead | CharWrite | CharWriteNR,
+		secure: secure,
+		// FIXME: currently, we always return 0, which is inaccurate.
+		// Each connection should have it's own copy of this value.
+		value: []byte{0x00, 0x00},
+		char:  c,
+	}
+	c.cccd = cd
+	c.descs = append(c.descs, cd)
+}
+
+// HandleNotifyFunc calls HandleNotify(NotifyHandlerFunc(f)).
+func (c *Characteristic) HandleNotifyFunc(f func(r Request, n Notifier)) {
+	c.HandleNotify(NotifyHandlerFunc(f))
+}
+
+// TODO
+// func (c *Characteristic) SubscribedCentrals() []Central{
+// }
+
+// Descriptor is a BLE descriptor
+type Descriptor struct {
+	uuid   UUID
+	char   *Characteristic
+	props  Property // enabled properties
+	secure Property // security enabled properties
+
+	h     uint16
+	value []byte
+
+	rhandler ReadHandler
+	whandler WriteHandler
+}
+
+// Handle returns the Handle of the descriptor.
+func (d *Descriptor) Handle() uint16 { return d.h }
+
+// SetHandle sets the Handle of the descriptor.
+func (d *Descriptor) SetHandle(h uint16) { d.h = h }
+
+// NewDescriptor creates and returns a Descriptor.
+func NewDescriptor(u UUID, h uint16, char *Characteristic) *Descriptor {
+	cd := &Descriptor{
+		uuid: u,
+		h:    h,
+		char: char,
+	}
+	return cd
+}
+
+// UUID returns the UUID of the descriptor.
+func (d *Descriptor) UUID() UUID {
+	return d.uuid
+}
+
+// Name returns the specificatin name of the descriptor.
+// If the UUID is not assigned, returns an empty string.
+func (d *Descriptor) Name() string {
+	return knownDescriptors[d.uuid.String()].Name
+}
+
+// Characteristic returns the containing characteristic of the descriptor.
+func (d *Descriptor) Characteristic() *Characteristic {
+	return d.char
+}
+
+// SetValue makes the descriptor support read requests, and returns a static value.
+// SetValue must be called before the containing service is added to a server.
+// SetValue panics if the descriptor has already configured with a ReadHandler.
+func (d *Descriptor) SetValue(b []byte) {
+	if d.rhandler != nil {
+		panic("descriptor has been configured with a read handler")
+	}
+	d.props |= CharRead
+	// d.secure |= CharRead
+	d.value = make([]byte, len(b))
+	copy(d.value, b)
+}
+
+// HandleRead makes the descriptor support read requests, and routes read requests to h.
+// HandleRead must be called before the containing service is added to a server.
+// HandleRead panics if the descriptor has been configured with a static value.
+func (d *Descriptor) HandleRead(h ReadHandler) {
+	if d.value != nil {
+		panic("descriptor has been configured with a static value")
+	}
+	d.props |= CharRead
+	// d.secure |= CharRead
+	d.rhandler = h
+}
+
+// HandleReadFunc calls HandleRead(ReadHandlerFunc(f)).
+func (d *Descriptor) HandleReadFunc(f func(rsp ResponseWriter, req *ReadRequest)) {
+	d.HandleRead(ReadHandlerFunc(f))
+}
+
+// HandleWrite makes the descriptor support write and write-no-response requests, and routes write requests to h.
+// The WriteHandler does not differentiate between write and write-no-response requests; it is handled automatically.
+// HandleWrite must be called before the containing service is added to a server.
+func (d *Descriptor) HandleWrite(h WriteHandler) {
+	d.props |= CharWrite | CharWriteNR
+	// d.secure |= CharWrite | CharWriteNR
+	d.whandler = h
+}
+
+// HandleWriteFunc calls HandleWrite(WriteHandlerFunc(f)).
+func (d *Descriptor) HandleWriteFunc(f func(r Request, data []byte) (status byte)) {
+	d.HandleWrite(WriteHandlerFunc(f))
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/const.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/const.go b/newtmgr/vendor/github.com/runtimeco/gatt/const.go
new file mode 100644
index 0000000..4a04b04
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/const.go
@@ -0,0 +1,153 @@
+package gatt
+
+// This file includes constants from the BLE spec.
+
+var (
+	attrGAPUUID  = UUID16(0x1800)
+	attrGATTUUID = UUID16(0x1801)
+
+	attrPrimaryServiceUUID   = UUID16(0x2800)
+	attrSecondaryServiceUUID = UUID16(0x2801)
+	attrIncludeUUID          = UUID16(0x2802)
+	attrCharacteristicUUID   = UUID16(0x2803)
+
+	attrClientCharacteristicConfigUUID = UUID16(0x2902)
+	attrServerCharacteristicConfigUUID = UUID16(0x2903)
+
+	attrDeviceNameUUID        = UUID16(0x2A00)
+	attrAppearanceUUID        = UUID16(0x2A01)
+	attrPeripheralPrivacyUUID = UUID16(0x2A02)
+	attrReconnectionAddrUUID  = UUID16(0x2A03)
+	attrPeferredParamsUUID    = UUID16(0x2A04)
+	attrServiceChangedUUID    = UUID16(0x2A05)
+)
+
+const (
+	gattCCCNotifyFlag   = 0x0001
+	gattCCCIndicateFlag = 0x0002
+)
+
+const (
+	attOpError              = 0x01
+	attOpMtuReq             = 0x02
+	attOpMtuRsp             = 0x03
+	attOpFindInfoReq        = 0x04
+	attOpFindInfoRsp        = 0x05
+	attOpFindByTypeValueReq = 0x06
+	attOpFindByTypeValueRsp = 0x07
+	attOpReadByTypeReq      = 0x08
+	attOpReadByTypeRsp      = 0x09
+	attOpReadReq            = 0x0a
+	attOpReadRsp            = 0x0b
+	attOpReadBlobReq        = 0x0c
+	attOpReadBlobRsp        = 0x0d
+	attOpReadMultiReq       = 0x0e
+	attOpReadMultiRsp       = 0x0f
+	attOpReadByGroupReq     = 0x10
+	attOpReadByGroupRsp     = 0x11
+	attOpWriteReq           = 0x12
+	attOpWriteRsp           = 0x13
+	attOpWriteCmd           = 0x52
+	attOpPrepWriteReq       = 0x16
+	attOpPrepWriteRsp       = 0x17
+	attOpExecWriteReq       = 0x18
+	attOpExecWriteRsp       = 0x19
+	attOpHandleNotify       = 0x1b
+	attOpHandleInd          = 0x1d
+	attOpHandleCnf          = 0x1e
+	attOpSignedWriteCmd     = 0xd2
+)
+
+type attEcode byte
+
+const (
+	attEcodeSuccess           attEcode = 0x00 // Success
+	attEcodeInvalidHandle     attEcode = 0x01 // The attribute handle given was not valid on this server.
+	attEcodeReadNotPerm       attEcode = 0x02 // The attribute cannot be read.
+	attEcodeWriteNotPerm      attEcode = 0x03 // The attribute cannot be written.
+	attEcodeInvalidPDU        attEcode = 0x04 // The attribute PDU was invalid.
+	attEcodeAuthentication    attEcode = 0x05 // The attribute requires authentication before it can be read or written.
+	attEcodeReqNotSupp        attEcode = 0x06 // Attribute server does not support the request received from the client.
+	attEcodeInvalidOffset     attEcode = 0x07 // Offset specified was past the end of the attribute.
+	attEcodeAuthorization     attEcode = 0x08 // The attribute requires authorization before it can be read or written.
+	attEcodePrepQueueFull     attEcode = 0x09 // Too many prepare writes have been queued.
+	attEcodeAttrNotFound      attEcode = 0x0a // No attribute found within the given attribute handle range.
+	attEcodeAttrNotLong       attEcode = 0x0b // The attribute cannot be read or written using the Read Blob Request.
+	attEcodeInsuffEncrKeySize attEcode = 0x0c // The Encryption Key Size used for encrypting this link is insufficient.
+	attEcodeInvalAttrValueLen attEcode = 0x0d // The attribute value length is invalid for the operation.
+	attEcodeUnlikely          attEcode = 0x0e // The attribute request that was requested has encountered an error that was unlikely, and therefore could not be completed as requested.
+	attEcodeInsuffEnc         attEcode = 0x0f // The attribute requires encryption before it can be read or written.
+	attEcodeUnsuppGrpType     attEcode = 0x10 // The attribute type is not a supported grouping attribute as defined by a higher layer specification.
+	attEcodeInsuffResources   attEcode = 0x11 // Insufficient Resources to complete the request.
+)
+
+func (a attEcode) Error() string {
+	switch i := int(a); {
+	case i < 0x11:
+		return attEcodeName[a]
+	case i >= 0x12 && i <= 0x7F: // Reserved for future use
+		return "reserved error code"
+	case i >= 0x80 && i <= 0x9F: // Application Error, defined by higher level
+		return "reserved error code"
+	case i >= 0xA0 && i <= 0xDF: // Reserved for future use
+		return "reserved error code"
+	case i >= 0xE0 && i <= 0xFF: // Common profile and service error codes
+		return "profile or service error"
+	default: // can't happen, just make compiler happy
+		return "unkown error"
+	}
+}
+
+var attEcodeName = map[attEcode]string{
+	attEcodeSuccess:           "success",
+	attEcodeInvalidHandle:     "invalid handle",
+	attEcodeReadNotPerm:       "read not permitted",
+	attEcodeWriteNotPerm:      "write not permitted",
+	attEcodeInvalidPDU:        "invalid PDU",
+	attEcodeAuthentication:    "insufficient authentication",
+	attEcodeReqNotSupp:        "request not supported",
+	attEcodeInvalidOffset:     "invalid offset",
+	attEcodeAuthorization:     "insufficient authorization",
+	attEcodePrepQueueFull:     "prepare queue full",
+	attEcodeAttrNotFound:      "attribute not found",
+	attEcodeAttrNotLong:       "attribute not long",
+	attEcodeInsuffEncrKeySize: "insufficient encryption key size",
+	attEcodeInvalAttrValueLen: "invalid attribute value length",
+	attEcodeUnlikely:          "unlikely error",
+	attEcodeInsuffEnc:         "insufficient encryption",
+	attEcodeUnsuppGrpType:     "unsupported group type",
+	attEcodeInsuffResources:   "insufficient resources",
+}
+
+func attErrorRsp(op byte, h uint16, s attEcode) []byte {
+	return attErr{opcode: op, attr: h, status: s}.Marshal()
+}
+
+// attRspFor maps from att request
+// codes to att response codes.
+var attRspFor = map[byte]byte{
+	attOpMtuReq:             attOpMtuRsp,
+	attOpFindInfoReq:        attOpFindInfoRsp,
+	attOpFindByTypeValueReq: attOpFindByTypeValueRsp,
+	attOpReadByTypeReq:      attOpReadByTypeRsp,
+	attOpReadReq:            attOpReadRsp,
+	attOpReadBlobReq:        attOpReadBlobRsp,
+	attOpReadMultiReq:       attOpReadMultiRsp,
+	attOpReadByGroupReq:     attOpReadByGroupRsp,
+	attOpWriteReq:           attOpWriteRsp,
+	attOpPrepWriteReq:       attOpPrepWriteRsp,
+	attOpExecWriteReq:       attOpExecWriteRsp,
+}
+
+type attErr struct {
+	opcode uint8
+	attr   uint16
+	status attEcode
+}
+
+// TODO: Reformulate in a way that lets the caller avoid allocs.
+// Accept a []byte? Write directly to an io.Writer?
+func (e attErr) Marshal() []byte {
+	// little-endian encoding for attr
+	return []byte{attOpError, e.opcode, byte(e.attr), byte(e.attr >> 8), byte(e.status)}
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/device.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/device.go b/newtmgr/vendor/github.com/runtimeco/gatt/device.go
new file mode 100644
index 0000000..eba96cf
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/device.go
@@ -0,0 +1,161 @@
+package gatt
+
+import "errors"
+
+var notImplemented = errors.New("not implemented")
+
+type State int
+
+const (
+	StateUnknown      State = 0
+	StateResetting    State = 1
+	StateUnsupported  State = 2
+	StateUnauthorized State = 3
+	StatePoweredOff   State = 4
+	StatePoweredOn    State = 5
+)
+
+func (s State) String() string {
+	str := []string{
+		"Unknown",
+		"Resetting",
+		"Unsupported",
+		"Unauthorized",
+		"PoweredOff",
+		"PoweredOn",
+	}
+	return str[int(s)]
+}
+
+// Device defines the interface for a BLE device.
+// Since an interface can't define fields(properties). To implement the
+// callback support for cerntain events, deviceHandler is defined and
+// implementation of Device on different platforms should embed it in
+// order to keep have keep compatible in API level.
+// Package users can use the Handler to set these handlers.
+type Device interface {
+	Init(stateChanged func(Device, State)) error
+
+	// Advertise advertise AdvPacket
+	Advertise(a *AdvPacket) error
+
+	// AdvertiseNameAndServices advertises device name, and specified service UUIDs.
+	// It tres to fit the UUIDs in the advertising packet as much as possible.
+	// If name doesn't fit in the advertising packet, it will be put in scan response.
+	AdvertiseNameAndServices(name string, ss []UUID) error
+
+	// AdvertiseIBeaconData advertise iBeacon with given manufacturer data.
+	AdvertiseIBeaconData(b []byte) error
+
+	// AdvertisingIbeacon advertises iBeacon with specified parameters.
+	AdvertiseIBeacon(u UUID, major, minor uint16, pwr int8) error
+
+	// StopAdvertising stops advertising.
+	StopAdvertising() error
+
+	// RemoveAllServices removes all services that are currently in the database.
+	RemoveAllServices() error
+
+	// Add Service add a service to database.
+	AddService(s *Service) error
+
+	// SetServices set the specified service to the database.
+	// It removes all currently added services, if any.
+	SetServices(ss []*Service) error
+
+	// Scan discovers surounding remote peripherals that have the Service UUID specified in ss.
+	// If ss is set to nil, all devices scanned are reported.
+	// dup specifies weather duplicated advertisement should be reported or not.
+	// When a remote peripheral is discovered, the PeripheralDiscovered Handler is called.
+	Scan(ss []UUID, dup bool)
+
+	// StopScanning stops scanning.
+	StopScanning()
+
+	// Connect connects to a remote peripheral.
+	Connect(p Peripheral)
+
+	// CancelConnection disconnects a remote peripheral.
+	CancelConnection(p Peripheral)
+
+	// Handle registers the specified handlers.
+	Handle(h ...Handler)
+
+	// Stop HCI Connection
+        Stop() error
+
+	// Option sets the options specified.
+	Option(o ...Option) error
+}
+
+// deviceHandler is the handlers(callbacks) of the Device.
+type deviceHandler struct {
+	// stateChanged is called when the device states changes.
+	stateChanged func(d Device, s State)
+
+	// connect is called when a remote central device connects to the device.
+	centralConnected func(c Central)
+
+	// disconnect is called when a remote central device disconnects to the device.
+	centralDisconnected func(c Central)
+
+	// peripheralDiscovered is called when a remote peripheral device is found during scan procedure.
+	peripheralDiscovered func(p Peripheral, a *Advertisement, rssi int)
+
+	// peripheralConnected is called when a remote peripheral is conneted.
+	peripheralConnected func(p Peripheral, err error)
+
+	// peripheralConnected is called when a remote peripheral is disconneted.
+	peripheralDisconnected func(p Peripheral, err error)
+}
+
+// A Handler is a self-referential function, which registers the options specified.
+// See http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html for more discussion.
+type Handler func(Device)
+
+// Handle registers the specified handlers.
+func (d *device) Handle(hh ...Handler) {
+	for _, h := range hh {
+		h(d)
+	}
+}
+
+// CentralConnected returns a Handler, which sets the specified function to be called when a device connects to the server.
+func CentralConnected(f func(Central)) Handler {
+	return func(d Device) { d.(*device).centralConnected = f }
+}
+
+// CentralDisconnected returns a Handler, which sets the specified function to be called when a device disconnects from the server.
+func CentralDisconnected(f func(Central)) Handler {
+	return func(d Device) { d.(*device).centralDisconnected = f }
+}
+
+// PeripheralDiscovered returns a Handler, which sets the specified function to be called when a remote peripheral device is found during scan procedure.
+func PeripheralDiscovered(f func(Peripheral, *Advertisement, int)) Handler {
+	return func(d Device) { d.(*device).peripheralDiscovered = f }
+}
+
+// PeripheralConnected returns a Handler, which sets the specified function to be called when a remote peripheral device connects.
+func PeripheralConnected(f func(Peripheral, error)) Handler {
+	return func(d Device) { d.(*device).peripheralConnected = f }
+}
+
+// PeripheralDisconnected returns a Handler, which sets the specified function to be called when a remote peripheral device disconnects.
+func PeripheralDisconnected(f func(Peripheral, error)) Handler {
+	return func(d Device) { d.(*device).peripheralDisconnected = f }
+}
+
+// An Option is a self-referential function, which sets the option specified.
+// Most Options are platform-specific, which gives more fine-grained control over the device at a cost of losing portibility.
+// See http://commandcenter.blogspot.com.au/2014/01/self-referential-functions-and-design.html for more discussion.
+type Option func(Device) error
+
+// Option sets the options specified.
+// Some options can only be set before the device is initialized; they are best used with NewDevice instead of Option.
+func (d *device) Option(opts ...Option) error {
+	var err error
+	for _, opt := range opts {
+		err = opt(d)
+	}
+	return err
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/device_darwin.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/device_darwin.go b/newtmgr/vendor/github.com/runtimeco/gatt/device_darwin.go
new file mode 100644
index 0000000..acf4431
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/device_darwin.go
@@ -0,0 +1,513 @@
+package gatt
+
+import (
+	"bytes"
+	"encoding/binary"
+	"errors"
+	"fmt"
+	"log"
+	"sync"
+	"time"
+
+	"github.com/runtimeco/gatt/xpc"
+)
+
+const (
+	peripheralDiscovered   = 37
+	peripheralConnected    = 38
+	peripheralDisconnected = 40
+	// below constants for Yosemite
+	rssiRead                   = 55
+	includedServicesDiscovered = 63
+	serviceDiscovered          = 56
+	characteristicsDiscovered  = 64
+	characteristicRead         = 71
+	characteristicWritten      = 72
+	notificationValueSet       = 74
+	descriptorsDiscovered      = 76
+	descriptorRead             = 79
+	descriptorWritten          = 80
+)
+
+type device struct {
+	deviceHandler
+
+	conn xpc.XPC
+
+	role int // 1: peripheralManager (server), 0: centralManager (client)
+
+	reqc chan message
+	rspc chan message
+
+	// Only used in client/centralManager implementation
+	plist   map[string]*peripheral
+	plistmu *sync.Mutex
+
+	// Only used in server/peripheralManager implementation
+
+	attrN int
+	attrs map[int]*attr
+
+	subscribers map[string]*central
+}
+
+func NewDevice(opts ...Option) (Device, error) {
+	d := &device{
+		reqc:    make(chan message),
+		rspc:    make(chan message),
+		plist:   map[string]*peripheral{},
+		plistmu: &sync.Mutex{},
+
+		attrN: 1,
+		attrs: make(map[int]*attr),
+
+		subscribers: make(map[string]*central),
+	}
+	d.Option(opts...)
+	d.conn = xpc.XpcConnect("com.apple.blued", d)
+	return d, nil
+}
+
+func (d *device) Init(f func(Device, State)) error {
+	go d.loop()
+	rsp := d.sendReq(1, xpc.Dict{
+		"kCBMsgArgName":    fmt.Sprintf("gopher-%v", time.Now().Unix()),
+		"kCBMsgArgOptions": xpc.Dict{"kCBInitOptionShowPowerAlert": 1},
+		"kCBMsgArgType":    d.role,
+	})
+	d.stateChanged = f
+	go d.stateChanged(d, State(rsp.MustGetInt("kCBMsgArgState")))
+	return nil
+}
+
+func (d *device) Advertise(a *AdvPacket) error {
+	rsp := d.sendReq(8, xpc.Dict{
+		"kCBAdvDataAppleMfgData": a.b, // not a.Bytes(). should be slice
+	})
+
+	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
+		return errors.New("FIXME: Advertise error")
+	}
+	return nil
+}
+
+func (d *device) AdvertiseNameAndServices(name string, ss []UUID) error {
+	us := uuidSlice(ss)
+	rsp := d.sendReq(8, xpc.Dict{
+		"kCBAdvDataLocalName":    name,
+		"kCBAdvDataServiceUUIDs": us},
+	)
+	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
+		return errors.New("FIXME: Advertise error")
+	}
+	return nil
+}
+
+func (d *device) AdvertiseIBeaconData(data []byte) error {
+	var utsname xpc.Utsname
+	xpc.Uname(&utsname)
+
+	var rsp xpc.Dict
+
+	if utsname.Release >= "14." {
+		l := len(data)
+		buf := bytes.NewBuffer([]byte{byte(l + 5), 0xFF, 0x4C, 0x00, 0x02, byte(l)})
+		buf.Write(data)
+		rsp = d.sendReq(8, xpc.Dict{"kCBAdvDataAppleMfgData": buf.Bytes()})
+	} else {
+		rsp = d.sendReq(8, xpc.Dict{"kCBAdvDataAppleBeaconKey": data})
+	}
+
+	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
+		return errors.New("FIXME: Advertise error")
+	}
+
+	return nil
+}
+
+func (d *device) AdvertiseIBeacon(u UUID, major, minor uint16, pwr int8) error {
+	b := make([]byte, 21)
+	copy(b, reverse(u.b))                     // Big endian
+	binary.BigEndian.PutUint16(b[16:], major) // Big endian
+	binary.BigEndian.PutUint16(b[18:], minor) // Big endian
+	b[20] = uint8(pwr)                        // Measured Tx Power
+	return d.AdvertiseIBeaconData(b)
+}
+
+func (d *device) StopAdvertising() error {
+	rsp := d.sendReq(9, nil)
+	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
+		return errors.New("FIXME: Stop Advertise error")
+	}
+	return nil
+}
+
+func (d *device) RemoveAllServices() error {
+	d.sendCmd(12, nil)
+	return nil
+}
+
+func (d *device) AddService(s *Service) error {
+	if s.uuid.Equal(attrGAPUUID) || s.uuid.Equal(attrGATTUUID) {
+		// skip GATT and GAP services
+		return nil
+	}
+
+	xs := xpc.Dict{
+		"kCBMsgArgAttributeID":     d.attrN,
+		"kCBMsgArgAttributeIDs":    []int{},
+		"kCBMsgArgCharacteristics": nil,
+		"kCBMsgArgType":            1, // 1 => primary, 0 => excluded
+		"kCBMsgArgUUID":            reverse(s.uuid.b),
+	}
+	d.attrN++
+
+	xcs := xpc.Array{}
+	for _, c := range s.Characteristics() {
+		props := 0
+		perm := 0
+		if c.props&CharRead != 0 {
+			props |= 0x02
+			if CharRead&c.secure != 0 {
+				perm |= 0x04
+			} else {
+				perm |= 0x01
+			}
+		}
+		if c.props&CharWriteNR != 0 {
+			props |= 0x04
+			if c.secure&CharWriteNR != 0 {
+				perm |= 0x08
+			} else {
+				perm |= 0x02
+			}
+		}
+		if c.props&CharWrite != 0 {
+			props |= 0x08
+			if c.secure&CharWrite != 0 {
+				perm |= 0x08
+			} else {
+				perm |= 0x02
+			}
+		}
+		if c.props&CharNotify != 0 {
+			if c.secure&CharNotify != 0 {
+				props |= 0x100
+			} else {
+				props |= 0x10
+			}
+		}
+		if c.props&CharIndicate != 0 {
+			if c.secure&CharIndicate != 0 {
+				props |= 0x200
+			} else {
+				props |= 0x20
+			}
+		}
+
+		xc := xpc.Dict{
+			"kCBMsgArgAttributeID":              d.attrN,
+			"kCBMsgArgUUID":                     reverse(c.uuid.b),
+			"kCBMsgArgAttributePermissions":     perm,
+			"kCBMsgArgCharacteristicProperties": props,
+			"kCBMsgArgData":                     c.value,
+		}
+		d.attrs[d.attrN] = &attr{h: uint16(d.attrN), value: c.value, pvt: c}
+		d.attrN++
+
+		xds := xpc.Array{}
+		for _, d := range c.Descriptors() {
+			if d.uuid.Equal(attrClientCharacteristicConfigUUID) {
+				// skip CCCD
+				continue
+			}
+			xd := xpc.Dict{
+				"kCBMsgArgData": d.value,
+				"kCBMsgArgUUID": reverse(d.uuid.b),
+			}
+			xds = append(xds, xd)
+		}
+		xc["kCBMsgArgDescriptors"] = xds
+		xcs = append(xcs, xc)
+	}
+	xs["kCBMsgArgCharacteristics"] = xcs
+
+	rsp := d.sendReq(10, xs)
+	if res := rsp.MustGetInt("kCBMsgArgResult"); res != 0 {
+		return errors.New("FIXME: Add Srvice error")
+	}
+	return nil
+}
+
+func (d *device) SetServices(ss []*Service) error {
+	d.RemoveAllServices()
+	for _, s := range ss {
+		d.AddService(s)
+	}
+	return nil
+}
+
+func (d *device) Scan(ss []UUID, dup bool) {
+	args := xpc.Dict{
+		"kCBMsgArgUUIDs": uuidSlice(ss),
+		"kCBMsgArgOptions": xpc.Dict{
+			"kCBScanOptionAllowDuplicates": map[bool]int{true: 1, false: 0}[dup],
+		},
+	}
+	d.sendCmd(29, args)
+}
+
+func (d *device) StopScanning() {
+	d.sendCmd(30, nil)
+}
+
+func (d *device) Connect(p Peripheral) {
+	pp := p.(*peripheral)
+	d.plist[pp.id.String()] = pp
+	d.sendCmd(31,
+		xpc.Dict{
+			"kCBMsgArgDeviceUUID": pp.id,
+			"kCBMsgArgOptions": xpc.Dict{
+				"kCBConnectOptionNotifyOnDisconnection": 1,
+			},
+		})
+}
+
+func (d *device) respondToRequest(id int, args xpc.Dict) {
+
+	switch id {
+	case 19: // ReadRequest
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		t := args.MustGetInt("kCBMsgArgTransactionID")
+		a := args.MustGetInt("kCBMsgArgAttributeID")
+		o := args.MustGetInt("kCBMsgArgOffset")
+
+		attr := d.attrs[a]
+		v := attr.value
+		if v == nil {
+			c := newCentral(d, u)
+			req := &ReadRequest{
+				Request: Request{Central: c},
+				Cap:     int(c.mtu - 1),
+				Offset:  o,
+			}
+			rsp := newResponseWriter(int(c.mtu - 1))
+			if c, ok := attr.pvt.(*Characteristic); ok {
+				c.rhandler.ServeRead(rsp, req)
+				v = rsp.bytes()
+			}
+		}
+
+		d.sendCmd(13, xpc.Dict{
+			"kCBMsgArgAttributeID":   a,
+			"kCBMsgArgData":          v,
+			"kCBMsgArgTransactionID": t,
+			"kCBMsgArgResult":        0,
+		})
+
+	case 20: // WriteRequest
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		t := args.MustGetInt("kCBMsgArgTransactionID")
+		a := 0
+		noRsp := false
+		xxws := args.MustGetArray("kCBMsgArgATTWrites")
+		for _, xxw := range xxws {
+			xw := xxw.(xpc.Dict)
+			if a == 0 {
+				a = xw.MustGetInt("kCBMsgArgAttributeID")
+			}
+			o := xw.MustGetInt("kCBMsgArgOffset")
+			i := xw.MustGetInt("kCBMsgArgIgnoreResponse")
+			b := xw.MustGetBytes("kCBMsgArgData")
+			_ = o
+			attr := d.attrs[a]
+			c := newCentral(d, u)
+			r := Request{Central: c}
+			attr.pvt.(*Characteristic).whandler.ServeWrite(r, b)
+			if i == 1 {
+				noRsp = true
+			}
+
+		}
+		if noRsp {
+			break
+		}
+		d.sendCmd(13, xpc.Dict{
+			"kCBMsgArgAttributeID":   a,
+			"kCBMsgArgData":          nil,
+			"kCBMsgArgTransactionID": t,
+			"kCBMsgArgResult":        0,
+		})
+
+	case 21: // subscribed
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		a := args.MustGetInt("kCBMsgArgAttributeID")
+		attr := d.attrs[a]
+		c := newCentral(d, u)
+		d.subscribers[u.String()] = c
+		c.startNotify(attr, c.mtu)
+
+	case 22: // unubscribed
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		a := args.MustGetInt("kCBMsgArgAttributeID")
+		attr := d.attrs[a]
+		if c := d.subscribers[u.String()]; c != nil {
+			c.stopNotify(attr)
+		}
+
+	case 23: // notificationSent
+	}
+}
+
+/*
+ * OSX GATT library currently doesn't work for Mynewt, so adding this stub to keep
+ * it buildable for OSX.
+ */
+func (d *device) Stop() error {
+	return nil
+}
+
+func (d *device) CancelConnection(p Peripheral) {
+	d.sendCmd(32, xpc.Dict{"kCBMsgArgDeviceUUID": p.(*peripheral).id})
+}
+
+// process device events and asynchronous errors
+// (implements XpcEventHandler)
+func (d *device) HandleXpcEvent(event xpc.Dict, err error) {
+	if err != nil {
+		log.Println("error:", err)
+		return
+	}
+
+	id := event.MustGetInt("kCBMsgId")
+	args := event.MustGetDict("kCBMsgArgs")
+	//log.Printf(">> %d, %v", id, args)
+
+	switch id {
+	case // device event
+		6,  // StateChanged
+		16, // AdvertisingStarted
+		17, // AdvertisingStopped
+		18: // ServiceAdded
+		d.rspc <- message{id: id, args: args}
+
+	case
+		19, // ReadRequest
+		20, // WriteRequest
+		21, // Subscribe
+		22, // Unubscribe
+		23: // Confirmation
+		d.respondToRequest(id, args)
+
+	case peripheralDiscovered:
+		xa := args.MustGetDict("kCBMsgArgAdvertisementData")
+		if len(xa) == 0 {
+			return
+		}
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		a := &Advertisement{
+			LocalName:        xa.GetString("kCBAdvDataLocalName", args.GetString("kCBMsgArgName", "")),
+			TxPowerLevel:     xa.GetInt("kCBAdvDataTxPowerLevel", 0),
+			ManufacturerData: xa.GetBytes("kCBAdvDataManufacturerData", nil),
+		}
+
+		rssi := args.MustGetInt("kCBMsgArgRssi")
+
+		if xu, ok := xa["kCBAdvDataServiceUUIDs"]; ok {
+			for _, xs := range xu.(xpc.Array) {
+				s := UUID{reverse(xs.([]byte))}
+				a.Services = append(a.Services, s)
+			}
+		}
+		if xsds, ok := xa["kCBAdvDataServiceData"]; ok {
+			xsd := xsds.(xpc.Array)
+			for i := 0; i < len(xsd); i += 2 {
+				sd := ServiceData{
+					UUID: UUID{xsd[i].([]byte)},
+					Data: xsd[i+1].([]byte),
+				}
+				a.ServiceData = append(a.ServiceData, sd)
+			}
+		}
+		if d.peripheralDiscovered != nil {
+			go d.peripheralDiscovered(&peripheral{id: xpc.UUID(u.b), d: d}, a, rssi)
+		}
+
+	case peripheralConnected:
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		p := &peripheral{
+			id:    xpc.UUID(u.b),
+			d:     d,
+			reqc:  make(chan message),
+			rspc:  make(chan message),
+			quitc: make(chan struct{}),
+			sub:   newSubscriber(),
+		}
+		d.plistmu.Lock()
+		d.plist[u.String()] = p
+		d.plistmu.Unlock()
+		go p.loop()
+
+		if d.peripheralConnected != nil {
+			go d.peripheralConnected(p, nil)
+		}
+
+	case peripheralDisconnected:
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		d.plistmu.Lock()
+		p := d.plist[u.String()]
+		delete(d.plist, u.String())
+		d.plistmu.Unlock()
+		if d.peripheralDisconnected != nil {
+			d.peripheralDisconnected(p, nil) // TODO: Get Result as error?
+		}
+		close(p.quitc)
+
+	case // Peripheral events
+		rssiRead,
+		serviceDiscovered,
+		includedServicesDiscovered,
+		characteristicsDiscovered,
+		characteristicRead,
+		characteristicWritten,
+		notificationValueSet,
+		descriptorsDiscovered,
+		descriptorRead,
+		descriptorWritten:
+
+		u := UUID{args.MustGetUUID("kCBMsgArgDeviceUUID")}
+		d.plistmu.Lock()
+		p := d.plist[u.String()]
+		d.plistmu.Unlock()
+		p.rspc <- message{id: id, args: args}
+
+	default:
+		log.Printf("Unhandled event: %#v", event)
+	}
+}
+
+func (d *device) sendReq(id int, args xpc.Dict) xpc.Dict {
+	m := message{id: id, args: args, rspc: make(chan xpc.Dict)}
+	d.reqc <- m
+	return <-m.rspc
+}
+
+func (d *device) sendCmd(id int, args xpc.Dict) {
+	d.reqc <- message{id: id, args: args}
+}
+
+func (d *device) loop() {
+	for req := range d.reqc {
+		d.sendCBMsg(req.id, req.args)
+		if req.rspc == nil {
+			continue
+		}
+		m := <-d.rspc
+		req.rspc <- m.args
+	}
+}
+
+func (d *device) sendCBMsg(id int, args xpc.Dict) {
+	// log.Printf("<< %d, %v", id, args)
+	d.conn.Send(xpc.Dict{"kCBMsgId": id, "kCBMsgArgs": args}, false)
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/abf65d3a/newtmgr/vendor/github.com/runtimeco/gatt/device_linux.go
----------------------------------------------------------------------
diff --git a/newtmgr/vendor/github.com/runtimeco/gatt/device_linux.go b/newtmgr/vendor/github.com/runtimeco/gatt/device_linux.go
new file mode 100644
index 0000000..4c989e1
--- /dev/null
+++ b/newtmgr/vendor/github.com/runtimeco/gatt/device_linux.go
@@ -0,0 +1,240 @@
+package gatt
+
+import (
+	"encoding/binary"
+	"net"
+
+	"github.com/runtimeco/gatt/linux"
+	"github.com/runtimeco/gatt/linux/cmd"
+)
+
+type device struct {
+	deviceHandler
+
+	hci   *linux.HCI
+	state State
+
+	// All the following fields are only used peripheralManager (server) implementation.
+	svcs  []*Service
+	attrs *attrRange
+
+	devID   int
+	chkLE   bool
+	maxConn int
+
+	advData   *cmd.LESetAdvertisingData
+	scanResp  *cmd.LESetScanResponseData
+	advParam  *cmd.LESetAdvertisingParameters
+	scanParam *cmd.LESetScanParameters
+}
+
+func NewDevice(opts ...Option) (Device, error) {
+	d := &device{
+		maxConn: 1,    // Support 1 connection at a time.
+		devID:   -1,   // Find an available HCI device.
+		chkLE:   true, // Check if the device supports LE.
+
+		advParam: &cmd.LESetAdvertisingParameters{
+			AdvertisingIntervalMin:  0x800,     // [0x0800]: 0.625 ms * 0x0800 = 1280.0 ms
+			AdvertisingIntervalMax:  0x800,     // [0x0800]: 0.625 ms * 0x0800 = 1280.0 ms
+			AdvertisingType:         0x00,      // [0x00]: ADV_IND, 0x01: DIRECT(HIGH), 0x02: SCAN, 0x03: NONCONN, 0x04: DIRECT(LOW)
+			OwnAddressType:          0x00,      // [0x00]: public, 0x01: random
+			DirectAddressType:       0x00,      // [0x00]: public, 0x01: random
+			DirectAddress:           [6]byte{}, // Public or Random Address of the device to be connected
+			AdvertisingChannelMap:   0x7,       // [0x07] 0x01: ch37, 0x2: ch38, 0x4: ch39
+			AdvertisingFilterPolicy: 0x00,
+		},
+		scanParam: &cmd.LESetScanParameters{
+			LEScanType:           0x01,   // [0x00]: passive, 0x01: active
+			LEScanInterval:       0x0010, // [0x10]: 0.625ms * 16
+			LEScanWindow:         0x0010, // [0x10]: 0.625ms * 16
+			OwnAddressType:       0x00,   // [0x00]: public, 0x01: random
+			ScanningFilterPolicy: 0x00,   // [0x00]: accept all, 0x01: ignore non-white-listed.
+		},
+	}
+
+	d.Option(opts...)
+	h, err := linux.NewHCI(d.devID, d.chkLE, d.maxConn)
+	if err != nil {
+		return nil, err
+	}
+
+	d.hci = h
+	return d, nil
+}
+
+func (d *device) Init(f func(Device, State)) error {
+	d.hci.AcceptMasterHandler = func(pd *linux.PlatData) {
+		a := pd.Address
+		c := newCentral(d.attrs, net.HardwareAddr([]byte{a[5], a[4], a[3], a[2], a[1], a[0]}), pd.Conn)
+		if d.centralConnected != nil {
+			d.centralConnected(c)
+		}
+		c.loop()
+		if d.centralDisconnected != nil {
+			d.centralDisconnected(c)
+		}
+	}
+	d.hci.AcceptSlaveHandler = func(pd *linux.PlatData) {
+		p := &peripheral{
+			d:     d,
+			pd:    pd,
+			l2c:   pd.Conn,
+			reqc:  make(chan message),
+			quitc: make(chan struct{}),
+			sub:   newSubscriber(),
+		}
+		if d.peripheralConnected != nil {
+			go d.peripheralConnected(p, nil)
+		}
+		p.loop()
+		if d.peripheralDisconnected != nil {
+			d.peripheralDisconnected(p, nil)
+		}
+	}
+	d.hci.AdvertisementHandler = func(pd *linux.PlatData) {
+		a := &Advertisement{}
+		a.unmarshall(pd.Data)
+		a.Connectable = pd.Connectable
+	        a.Address = pd.Address
+		a.AddressType = pd.AddressType
+		p := &peripheral{pd: pd, d: d}
+		if d.peripheralDiscovered != nil {
+			pd.Name = a.LocalName
+			d.peripheralDiscovered(p, a, int(pd.RSSI))
+		}
+	}
+	d.state = StatePoweredOn
+	d.stateChanged = f
+	go d.stateChanged(d, d.state)
+	return nil
+}
+
+func (d *device) Stop() error {
+	d.state = StatePoweredOff
+	defer d.stateChanged(d, d.state)
+	return d.hci.Close()
+}
+
+func (d *device) AddService(s *Service) error {
+	d.svcs = append(d.svcs, s)
+	d.attrs = generateAttributes(d.svcs, uint16(1)) // ble attrs start at 1
+	return nil
+}
+
+func (d *device) RemoveAllServices() error {
+	d.svcs = nil
+	d.attrs = nil
+	return nil
+}
+
+func (d *device) SetServices(s []*Service) error {
+	d.RemoveAllServices()
+	d.svcs = append(d.svcs, s...)
+	d.attrs = generateAttributes(d.svcs, uint16(1)) // ble attrs start at 1
+	return nil
+}
+
+func (d *device) Advertise(a *AdvPacket) error {
+	d.advData = &cmd.LESetAdvertisingData{
+		AdvertisingDataLength: uint8(a.Len()),
+		AdvertisingData:       a.Bytes(),
+	}
+
+	if err := d.update(); err != nil {
+		return err
+	}
+
+	return d.hci.SetAdvertiseEnable(true)
+}
+
+func (d *device) AdvertiseNameAndServices(name string, uu []UUID) error {
+	a := &AdvPacket{}
+	a.AppendFlags(flagGeneralDiscoverable | flagLEOnly)
+	a.AppendUUIDFit(uu)
+
+	if len(a.b)+len(name)+2 < MaxEIRPacketLength {
+		a.AppendName(name)
+		d.scanResp = nil
+	} else {
+		a := &AdvPacket{}
+		a.AppendName(name)
+		d.scanResp = &cmd.LESetScanResponseData{
+			ScanResponseDataLength: uint8(a.Len()),
+			ScanResponseData:       a.Bytes(),
+		}
+	}
+
+	return d.Advertise(a)
+}
+
+func (d *device) AdvertiseIBeaconData(b []byte) error {
+	a := &AdvPacket{}
+	a.AppendFlags(flagGeneralDiscoverable | flagLEOnly)
+	a.AppendManufacturerData(0x004C, b)
+	d.advData = &cmd.LESetAdvertisingData{
+		AdvertisingDataLength: uint8(a.Len()),
+		AdvertisingData:       a.Bytes(),
+	}
+
+	return d.Advertise(a)
+}
+
+func (d *device) AdvertiseIBeacon(u UUID, major, minor uint16, pwr int8) error {
+	b := make([]byte, 23)
+	b[0] = 0x02                               // Data type: iBeacon
+	b[1] = 0x15                               // Data length: 21 bytes
+	copy(b[2:], reverse(u.b))                 // Big endian
+	binary.BigEndian.PutUint16(b[18:], major) // Big endian
+	binary.BigEndian.PutUint16(b[20:], minor) // Big endian
+	b[22] = uint8(pwr)                        // Measured Tx Power
+	return d.AdvertiseIBeaconData(b)
+}
+
+func (d *device) StopAdvertising() error {
+	return d.hci.SetAdvertiseEnable(false)
+}
+
+func (d *device) Scan(ss []UUID, dup bool) {
+	// TODO: filter
+	d.hci.SetScanEnable(true, dup)
+}
+
+func (d *device) StopScanning() {
+	d.hci.SetScanEnable(false, true)
+}
+
+func (d *device) Connect(p Peripheral) {
+	d.hci.Connect(p.(*peripheral).pd)
+}
+
+func (d *device) CancelConnection(p Peripheral) {
+	d.hci.CancelConnection(p.(*peripheral).pd)
+}
+
+func (d *device) SendHCIRawCommand(c cmd.CmdParam) ([]byte, error) {
+	return d.hci.SendRawCommand(c)
+}
+
+// Flush pending advertising settings to the device.
+func (d *device) update() error {
+	if d.advParam != nil {
+		if err := d.hci.SendCmdWithAdvOff(d.advParam); err != nil {
+			return err
+		}
+		d.advParam = nil
+	}
+	if d.scanResp != nil {
+		if err := d.hci.SendCmdWithAdvOff(d.scanResp); err != nil {
+			return err
+		}
+		d.scanResp = nil
+	}
+	if d.advData != nil {
+		if err := d.hci.SendCmdWithAdvOff(d.advData); err != nil {
+			return err
+		}
+		d.advData = nil
+	}
+	return nil
+}