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/05/16 21:54:15 UTC
incubator-mynewt-newtmgr git commit: nmxact - Device discovery.
Repository: incubator-mynewt-newtmgr
Updated Branches:
refs/heads/master fc22b9fa5 -> 822cea97d
nmxact - Device discovery.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/822cea97
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/822cea97
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/822cea97
Branch: refs/heads/master
Commit: 822cea97dd33b02255269392be0ea7aa9472d709
Parents: fc22b9f
Author: Christopher Collins <cc...@apache.org>
Authored: Mon May 1 14:21:54 2017 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue May 16 14:49:35 2017 -0700
----------------------------------------------------------------------
nmxact/bledefs/bledefs.go | 17 ++++
nmxact/example/ble_dual/ble_dual.go | 35 +++++++-
nmxact/example/ble_scan/ble_scan.go | 144 +++++++++++++++++++++++++++++
nmxact/nmble/ble_act.go | 55 ++++++++++--
nmxact/nmble/ble_fsm.go | 150 +++++++++++++++++++++----------
nmxact/nmble/ble_oic_sesn.go | 5 ++
nmxact/nmble/ble_plain_sesn.go | 4 +
nmxact/nmble/ble_proto.go | 39 +++++++-
nmxact/nmble/ble_scanner.go | 127 ++++++++++++++++++++++++++
nmxact/nmble/ble_util.go | 14 +--
nmxact/nmble/ble_xport.go | 18 +++-
nmxact/nmble/dispatch.go | 38 ++++----
nmxact/nmserial/serial_xport.go | 5 ++
nmxact/nmxutil/nmxutil.go | 77 +++++++++++++---
nmxact/scan/scan.go | 48 ++++++++++
nmxact/sesn/sesn_cfg.go | 2 +
nmxact/xport/xport.go | 3 +
17 files changed, 685 insertions(+), 96 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/bledefs/bledefs.go
----------------------------------------------------------------------
diff --git a/nmxact/bledefs/bledefs.go b/nmxact/bledefs/bledefs.go
index b811dc0..3d7e85b 100644
--- a/nmxact/bledefs/bledefs.go
+++ b/nmxact/bledefs/bledefs.go
@@ -29,6 +29,15 @@ import (
const BLE_ATT_ATTR_MAX_LEN = 512
+const NmpPlainSvcUuid = "8D53DC1D-1DB7-4CD3-868B-8A527460AA84"
+const NmpPlainChrUuid = "DA2E7828-FBCE-4E01-AE9E-261174997C48"
+const NmpOicSvcUuid = "ADE3D529-C784-4F63-A987-EB69F70EE816"
+const NmpOicReqChrUuid = "AD7B334F-4637-4B86-90B6-9D787F03D218"
+const NmpOicRspChrUuid = "E9241982-4580-42C4-8831-95048216B256"
+
+// This supersedes the 128-bit UUID above.
+const OmpSvcUuid = 0x9923
+
type BleAddrType int
const (
@@ -391,3 +400,11 @@ func (d *BleConnDesc) String() string {
BleAddrTypeToString(d.PeerOtaAddrType),
d.PeerOtaAddr.String())
}
+
+type BleEncryptWhen int
+
+const (
+ BLE_ENCRYPT_NEVER BleEncryptWhen = iota
+ BLE_ENCRYPT_PRIV_ONLY
+ BLE_ENCRYPT_ALWAYS
+)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/example/ble_dual/ble_dual.go
----------------------------------------------------------------------
diff --git a/nmxact/example/ble_dual/ble_dual.go b/nmxact/example/ble_dual/ble_dual.go
index 5be14e5..d446c3a 100644
--- a/nmxact/example/ble_dual/ble_dual.go
+++ b/nmxact/example/ble_dual/ble_dual.go
@@ -21,6 +21,7 @@ package main
import (
"fmt"
+ "io/ioutil"
"os"
"os/signal"
"sync"
@@ -31,6 +32,7 @@ import (
"mynewt.apache.org/newt/util"
"mynewt.apache.org/newtmgr/nmxact/bledefs"
"mynewt.apache.org/newtmgr/nmxact/nmble"
+ "mynewt.apache.org/newtmgr/nmxact/nmp"
"mynewt.apache.org/newtmgr/nmxact/nmxutil"
"mynewt.apache.org/newtmgr/nmxact/sesn"
"mynewt.apache.org/newtmgr/nmxact/xact"
@@ -144,6 +146,37 @@ func sendTaskStat(s sesn.Sesn) error {
return nil
}
+func sendImageUpload(s sesn.Sesn) error {
+ data, err := ioutil.ReadFile("/Users/ccollins/Downloads/f17c9295bfbbf8f6b31ddcfa835be095090d0a875edcf88116bfaeec55f27e93/app.img")
+ if err != nil {
+ return err
+ }
+
+ c := xact.NewImageUploadCmd()
+ c.Data = data
+ c.ProgressCb = func(c *xact.ImageUploadCmd, r *nmp.ImageUploadRsp) {
+ fmt.Printf("Rxed upload rsp: %d\n", r.Off)
+ }
+
+ res, err := c.Run(s)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error executing image upload command: %s\n",
+ err.Error())
+ panic(err.Error())
+ }
+
+ if res.Status() != 0 {
+ fmt.Printf("Peer responded negatively to image upload command; "+
+ "status=%d\n", res.Status())
+ panic("ERROR")
+ }
+
+ fmt.Printf("[%p] Peer responded with image upload: rc=%#v\n",
+ s, res.Status())
+
+ return nil
+}
+
func sendOne(s sesn.Sesn) {
// Repeatedly:
// * Connect to peer if unconnected.
@@ -183,7 +216,7 @@ func sendOne(s sesn.Sesn) {
}
func main() {
- nmxutil.SetLogLevel(log.InfoLevel)
+ nmxutil.SetLogLevel(log.DebugLevel)
// Initialize the BLE transport.
params := nmble.NewXportCfg()
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/example/ble_scan/ble_scan.go
----------------------------------------------------------------------
diff --git a/nmxact/example/ble_scan/ble_scan.go b/nmxact/example/ble_scan/ble_scan.go
new file mode 100644
index 0000000..d9f794c
--- /dev/null
+++ b/nmxact/example/ble_scan/ble_scan.go
@@ -0,0 +1,144 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package main
+
+import (
+ "fmt"
+ "os"
+ "os/signal"
+ "syscall"
+
+ log "github.com/Sirupsen/logrus"
+
+ "mynewt.apache.org/newt/util"
+ "mynewt.apache.org/newtmgr/nmxact/bledefs"
+ "mynewt.apache.org/newtmgr/nmxact/nmble"
+ "mynewt.apache.org/newtmgr/nmxact/nmxutil"
+ "mynewt.apache.org/newtmgr/nmxact/scan"
+ "mynewt.apache.org/newtmgr/nmxact/sesn"
+ "mynewt.apache.org/newtmgr/nmxact/xport"
+)
+
+func configExitHandler(x xport.Xport, s sesn.Sesn) {
+ onExit := func() {
+ if s != nil && s.IsOpen() {
+ s.Close()
+ }
+
+ x.Stop()
+ }
+
+ sigChan := make(chan os.Signal, 1)
+ signal.Notify(sigChan)
+
+ go func() {
+ for {
+ s := <-sigChan
+ switch s {
+ case os.Interrupt, syscall.SIGTERM:
+ onExit()
+ os.Exit(0)
+
+ case syscall.SIGQUIT:
+ util.PrintStacks()
+ }
+ }
+ }()
+}
+
+func main() {
+ //nmxutil.SetLogLevel(log.DebugLevel)
+ nmxutil.SetLogLevel(log.InfoLevel)
+
+ // Initialize the BLE transport.
+ params := nmble.NewXportCfg()
+ params.SockPath = "/tmp/blehostd-uds"
+ params.BlehostdPath = "blehostd.elf"
+ params.DevPath = "/dev/cu.usbmodem14221"
+
+ x, err := nmble.NewBleXport(params)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error creating BLE transport: %s\n",
+ err.Error())
+ os.Exit(1)
+ }
+
+ // Start the BLE transport.
+ if err := x.Start(); err != nil {
+ fmt.Fprintf(os.Stderr, "error starting BLE transport: %s\n",
+ err.Error())
+ os.Exit(1)
+ }
+ defer x.Stop()
+
+ scanChan := make(chan scan.ScanPeer)
+ scanCb := func(peer scan.ScanPeer) {
+ fmt.Printf("discovered peer: %#v\n", peer)
+ scanChan <- peer
+ }
+
+ configExitHandler(x, nil)
+
+ scanner, err := x.BuildScanner()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error building BLE scanner: %s\n",
+ err.Error())
+ os.Exit(1)
+ }
+
+ for {
+ sc := scan.BleOmpScanCfg(scanCb)
+ if err := scanner.Start(sc); err != nil {
+ fmt.Fprintf(os.Stderr, "error starting scan: %s\n", err.Error())
+ os.Exit(1)
+ }
+
+ p := <-scanChan
+
+ // Found a peer; stop scanning.
+ if err := scanner.Stop(); err != nil {
+ fmt.Fprintf(os.Stderr, "Failed to stop scan: %s\n", err.Error())
+ os.Exit(1)
+ }
+
+ fmt.Printf("Connecting to %#v\n", p)
+ c := sesn.NewSesnCfg()
+ c.MgmtProto = sesn.MGMT_PROTO_OMP
+ c.Ble.OwnAddrType = bledefs.BLE_ADDR_TYPE_RANDOM
+ c.Ble.PeerSpec = sesn.BlePeerSpecDev(p.Opaque.(bledefs.BleDev))
+
+ s, err := x.BuildSesn(c)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "error creating BLE session: %s\n",
+ err.Error())
+ os.Exit(1)
+ }
+
+ if err := s.Open(); err != nil {
+ fmt.Fprintf(os.Stderr, "error opening BLE session: %s\n",
+ err.Error())
+ os.Exit(1)
+ }
+
+ fmt.Printf("Connected\n")
+ fmt.Printf("Closing\n")
+ s.Close()
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_act.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_act.go b/nmxact/nmble/ble_act.go
index 4c5eef0..ed129cd 100644
--- a/nmxact/nmble/ble_act.go
+++ b/nmxact/nmble/ble_act.go
@@ -84,12 +84,12 @@ func connCancel(x *BleXport, bl *BleListener, r *BleConnCancelReq) error {
switch msg := bm.(type) {
case *BleConnCancelRsp:
bl.Acked = true
- if msg.Status != 0 {
+ if msg.Status != 0 && msg.Status != ERR_CODE_EALREADY {
return StatusError(MSG_OP_RSP, rspType, msg.Status)
- } else {
- return nil
}
+ return nil
+
default:
}
@@ -288,9 +288,8 @@ func exchangeMtu(x *BleXport, bl *BleListener, r *BleExchangeMtuReq) (
type scanSuccessFn func()
type advRptFn func(r BleAdvReport)
-func scan(x *BleXport, bl *BleListener, r *BleScanReq,
- abortChan chan struct{},
- scanSuccessCb scanSuccessFn, advRptCb advRptFn) error {
+func actScan(x *BleXport, bl *BleListener, r *BleScanReq,
+ abortChan chan struct{}, advRptCb advRptFn) error {
const rspType = MSG_TYPE_SCAN
@@ -314,8 +313,6 @@ func scan(x *BleXport, bl *BleListener, r *BleScanReq,
bl.Acked = true
if msg.Status != 0 {
return StatusError(MSG_OP_RSP, rspType, msg.Status)
- } else {
- scanSuccessCb()
}
case *BleScanEvt:
@@ -358,7 +355,7 @@ func scanCancel(x *BleXport, bl *BleListener, r *BleScanCancelReq) error {
switch msg := bm.(type) {
case *BleScanCancelRsp:
bl.Acked = true
- if msg.Status != 0 {
+ if msg.Status != 0 && msg.Status != ERR_CODE_EALREADY {
return StatusError(MSG_OP_RSP, rspType, msg.Status)
}
return nil
@@ -443,6 +440,46 @@ func reset(x *BleXport, bl *BleListener,
}
}
+// Blocking
+func encInitiate(x *BleXport, bl *BleListener, encChan chan error,
+ r *BleSecurityInitiateReq) error {
+
+ const rspType = MSG_TYPE_SECURITY_INITIATE
+
+ j, err := json.Marshal(r)
+ if err != nil {
+ return err
+ }
+
+ if err := x.Tx(j); err != nil {
+ return err
+ }
+
+ for {
+ select {
+ case err := <-bl.ErrChan:
+ return err
+
+ case bm := <-bl.BleChan:
+ switch msg := bm.(type) {
+ case *BleSecurityInitiateRsp:
+ bl.Acked = true
+ if msg.Status != 0 {
+ return StatusError(MSG_OP_RSP, rspType, msg.Status)
+ }
+
+ default:
+ }
+
+ case err := <-encChan:
+ return err
+
+ case <-bl.AfterTimeout(x.RspTimeout()):
+ return BhdTimeoutError(rspType, r.Seq)
+ }
+ }
+}
+
// Asks the controller to generate a random address. This is done when the
// transport is starting up, and therefore does not require the transport to be
// synced. Only the transport should call this function.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_fsm.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_fsm.go b/nmxact/nmble/ble_fsm.go
index 828997a..ed7b90b 100644
--- a/nmxact/nmble/ble_fsm.go
+++ b/nmxact/nmble/ble_fsm.go
@@ -34,10 +34,11 @@ const (
SESN_STATE_EXCHANGE_MTU = 3
SESN_STATE_DISCOVER_SVC = 4
SESN_STATE_DISCOVER_CHR = 5
- SESN_STATE_SUBSCRIBE = 6
- SESN_STATE_DONE = 7
- SESN_STATE_TERMINATING = 8
- SESN_STATE_CONN_CANCELLING = 9
+ SESN_STATE_SECURITY = 6
+ SESN_STATE_SUBSCRIBE = 7
+ SESN_STATE_DONE = 8
+ SESN_STATE_TERMINATING = 9
+ SESN_STATE_CONN_CANCELLING = 10
)
type BleFsmDisconnectType int
@@ -67,6 +68,7 @@ type BleFsmParams struct {
RspChrUuid BleUuid
RxNmpCb BleRxNmpFn
DisconnectCb BleDisconnectFn
+ Encrypt BleEncryptWhen
}
type BleFsm struct {
@@ -79,15 +81,13 @@ type BleFsm struct {
nmpRspChr *BleChr
attMtu int
connChan chan error
+ encChan chan error
bls map[*BleListener]struct{}
state BleSesnState
errFunnel nmxutil.ErrFunnel
id uint32
wg sync.WaitGroup
- // Gets notified when the FSM has stopped due to an error.
- errChan chan error
-
// Protects all accesses to the FSM state variable.
stateMtx sync.Mutex
@@ -207,8 +207,12 @@ func (bf *BleFsm) removeBleSeqListener(name string, seq BleSeq) {
bf.removeBleListener(name, base)
}
+func (bf *BleFsm) connInfo() (BleConnDesc, error) {
+ return ConnFindXact(bf.params.Bx, bf.connHandle)
+}
+
func (bf *BleFsm) logConnection() {
- desc, err := ConnFindXact(bf.params.Bx, bf.connHandle)
+ desc, err := bf.connInfo()
if err != nil {
return
}
@@ -263,19 +267,17 @@ func (bf *BleFsm) errorAll(err error) {
func (bf *BleFsm) processErr(err error) {
// Remember some fields before we clear them.
- dt := calcDisconnectType(bf.state)
+ dt := calcDisconnectType(bf.getState())
var peer BleDev
if bf.peerDev != nil {
peer = *bf.peerDev
}
+ bf.params.Bx.StopWaitingForMaster(bf, err)
bf.errorAll(err)
- bf.stateMtx.Lock()
- bf.state = SESN_STATE_UNCONNECTED
- bf.stateMtx.Unlock()
-
+ bf.setState(SESN_STATE_UNCONNECTED)
bf.peerDev = nil
// Wait for all listeners to get removed.
@@ -283,8 +285,6 @@ func (bf *BleFsm) processErr(err error) {
bf.errFunnel.Reset()
bf.params.DisconnectCb(dt, peer, err)
-
- bf.errChan <- err
}
func (bf *BleFsm) connectListen(seq BleSeq) error {
@@ -357,6 +357,21 @@ func (bf *BleFsm) connectListen(seq BleSeq) error {
bf.attMtu = int(msg.Mtu)
}
+ case *BleEncChangeEvt:
+ var err error
+ if msg.Status != 0 {
+ err = StatusError(MSG_OP_EVT,
+ MSG_TYPE_ENC_CHANGE_EVT,
+ msg.Status)
+ log.Debugf(err.Error())
+ } else {
+ log.Debugf("Connection encrypted; conn_handle=%d",
+ msg.ConnHandle)
+ }
+ if bf.encChan != nil {
+ bf.encChan <- err
+ }
+
case *BleDisconnectEvt:
err := bf.disconnectError(msg.Reason)
bf.errFunnel.Insert(err)
@@ -419,7 +434,7 @@ func (bf *BleFsm) connect() error {
r.PeerAddr = bf.peerDev.Addr
// Initiating a connection requires dedicated master privileges.
- if err := bf.params.Bx.AcquireMaster(); err != nil {
+ if err := bf.params.Bx.AcquireMaster(bf); err != nil {
return err
}
defer bf.params.Bx.ReleaseMaster()
@@ -439,7 +454,7 @@ func (bf *BleFsm) connect() error {
}
// Connection operation now in progress.
- bf.state = SESN_STATE_CONNECTING
+ bf.setState(SESN_STATE_CONNECTING)
err := <-bf.connChan
if !nmxutil.IsXport(err) {
@@ -447,11 +462,8 @@ func (bf *BleFsm) connect() error {
// operation. In most cases, the host has already stopped connecting
// and will respond with an "ealready" error that can be ignored.
if err := bf.connCancel(); err != nil {
- bhe := nmxutil.ToBleHost(err)
- if bhe == nil || bhe.Status != ERR_CODE_EALREADY {
- log.Errorf("Failed to cancel connect in progress: %s",
- err.Error())
- }
+ log.Errorf("Failed to cancel connect in progress: %s",
+ err.Error())
}
}
@@ -468,7 +480,7 @@ func (bf *BleFsm) scan() error {
r.FilterDuplicates = true
// Scanning requires dedicated master privileges.
- if err := bf.params.Bx.AcquireMaster(); err != nil {
+ if err := bf.params.Bx.AcquireMaster(bf); err != nil {
return err
}
defer bf.params.Bx.ReleaseMaster()
@@ -481,9 +493,6 @@ func (bf *BleFsm) scan() error {
abortChan := make(chan struct{}, 1)
- // This function gets called when scanning begins.
- scanSuccessCb := func() { bf.state = SESN_STATE_SCANNING }
-
// This function gets called for each incoming advertisement.
advRptCb := func(r BleAdvReport) {
// Ask client if we should connect to this advertiser.
@@ -493,17 +502,14 @@ func (bf *BleFsm) scan() error {
}
}
- err = scan(bf.params.Bx, bl, r, abortChan, scanSuccessCb, advRptCb)
+ err = actScan(bf.params.Bx, bl, r, abortChan, advRptCb)
if !nmxutil.IsXport(err) {
// The transport did not restart; always attempt to cancel the scan
// operation. In most cases, the host has already stopped scanning
// and will respond with an "ealready" error that can be ignored.
if err := bf.scanCancel(); err != nil {
- bhe := nmxutil.ToBleHost(err)
- if bhe == nil || bhe.Status != ERR_CODE_EALREADY {
- log.Errorf("Failed to cancel scan in progress: %s",
- err.Error())
- }
+ log.Errorf("Failed to cancel scan in progress: %s",
+ err.Error())
}
}
@@ -527,10 +533,7 @@ func (bf *BleFsm) scanCancel() error {
}
func (bf *BleFsm) terminateSetState() error {
- bf.stateMtx.Lock()
- defer bf.stateMtx.Unlock()
-
- switch bf.state {
+ switch bf.getState() {
case SESN_STATE_UNCONNECTED,
SESN_STATE_CONNECTING,
SESN_STATE_CONN_CANCELLING:
@@ -539,7 +542,7 @@ func (bf *BleFsm) terminateSetState() error {
return fmt.Errorf(
"BLE terminate failed; session already being closed")
default:
- bf.state = SESN_STATE_TERMINATING
+ bf.setState(SESN_STATE_TERMINATING)
}
return nil
@@ -602,6 +605,26 @@ func (bf *BleFsm) discSvcUuid() error {
return nil
}
+func (bf *BleFsm) encInitiate() error {
+ r := NewBleSecurityInitiateReq()
+ r.ConnHandle = bf.connHandle
+
+ bl, err := bf.addBleSeqListener("enc-initiate", r.Seq)
+ if err != nil {
+ return err
+ }
+ defer bf.removeBleSeqListener("enc-initiate", r.Seq)
+
+ bf.encChan = make(chan error, 1)
+ defer func() { bf.encChan = nil }()
+
+ if err := encInitiate(bf.params.Bx, bl, bf.encChan, r); err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (bf *BleFsm) discAllChrs() error {
r := NewBleDiscAllChrsReq()
r.ConnHandle = bf.connHandle
@@ -700,6 +723,24 @@ func (bf *BleFsm) subscribe() error {
return nil
}
+func (bf *BleFsm) shouldEncrypt() bool {
+ switch bf.params.Encrypt {
+ case BLE_ENCRYPT_NEVER:
+ return false
+
+ case BLE_ENCRYPT_ALWAYS:
+ return true
+
+ case BLE_ENCRYPT_PRIV_ONLY:
+ return bf.peerDev.AddrType == BLE_ADDR_TYPE_RPA_PUB ||
+ bf.peerDev.AddrType == BLE_ADDR_TYPE_RPA_RND
+
+ default:
+ panic(fmt.Sprintf("Invalid BleEncryptWhen value: %d",
+ bf.params.Encrypt))
+ }
+}
+
// Tries to populate the FSM's peerDev field. This function succeeds if the
// client specified the address of the peer to connect to.
func (bf *BleFsm) tryFillPeerDev() bool {
@@ -718,10 +759,7 @@ func (bf *BleFsm) tryFillPeerDev() bool {
}
func (bf *BleFsm) executeState() (bool, error) {
- bf.stateMtx.Lock()
- defer bf.stateMtx.Unlock()
-
- switch bf.state {
+ switch bf.getState() {
case SESN_STATE_UNCONNECTED:
// Determine if we can immediately initiate a connection, or if we
// need to scan for a peer first. If the client specified a peer
@@ -731,17 +769,18 @@ func (bf *BleFsm) executeState() (bool, error) {
bf.tryFillPeerDev()
if bf.peerDev == nil {
// Peer not inferred yet. Initiate scan.
+ bf.setState(SESN_STATE_SCANNING)
if err := bf.scan(); err != nil {
return false, err
}
- bf.state = SESN_STATE_UNCONNECTED
+ bf.setState(SESN_STATE_UNCONNECTED)
} else {
// We already know the address we want to connect to. Initiate
// a connection.
if err := bf.connect(); err != nil {
return false, err
}
- bf.state = SESN_STATE_EXCHANGE_MTU
+ bf.setState(SESN_STATE_EXCHANGE_MTU)
}
case SESN_STATE_EXCHANGE_MTU:
@@ -750,25 +789,35 @@ func (bf *BleFsm) executeState() (bool, error) {
retry := bhe != nil && bhe.Status == ERR_CODE_ENOTCONN
return retry, err
}
- bf.state = SESN_STATE_DISCOVER_SVC
+ bf.setState(SESN_STATE_DISCOVER_SVC)
case SESN_STATE_DISCOVER_SVC:
if err := bf.discSvcUuid(); err != nil {
return false, err
}
- bf.state = SESN_STATE_DISCOVER_CHR
+ bf.setState(SESN_STATE_DISCOVER_CHR)
case SESN_STATE_DISCOVER_CHR:
if err := bf.discAllChrs(); err != nil {
return false, err
}
- bf.state = SESN_STATE_SUBSCRIBE
+ if bf.shouldEncrypt() {
+ bf.setState(SESN_STATE_SECURITY)
+ } else {
+ bf.setState(SESN_STATE_SUBSCRIBE)
+ }
+
+ case SESN_STATE_SECURITY:
+ if err := bf.encInitiate(); err != nil {
+ return false, err
+ }
+ bf.setState(SESN_STATE_SUBSCRIBE)
case SESN_STATE_SUBSCRIBE:
if err := bf.subscribe(); err != nil {
return false, err
}
- bf.state = SESN_STATE_DONE
+ bf.setState(SESN_STATE_DONE)
case SESN_STATE_DONE:
/* Open complete. */
@@ -789,13 +838,12 @@ func (bf *BleFsm) startOnce() (bool, error) {
}
bf.errFunnel.Start()
- bf.errChan = make(chan error, 1)
for {
retry, err := bf.executeState()
if err != nil {
bf.errFunnel.Insert(err)
- err = <-bf.errChan
+ err = bf.errFunnel.Wait()
return retry, err
} else if bf.getState() == SESN_STATE_DONE {
return false, nil
@@ -837,6 +885,10 @@ func (bf *BleFsm) Stop() (bool, error) {
bf.errFunnel.Insert(fmt.Errorf("Connection attempt cancelled"))
return false, nil
+ case SESN_STATE_SCANNING:
+ bf.errFunnel.Insert(fmt.Errorf("Scan cancelled"))
+ return false, nil
+
default:
if err := bf.terminate(); err != nil {
return false, err
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_oic_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_oic_sesn.go b/nmxact/nmble/ble_oic_sesn.go
index 433ecb0..b390738 100644
--- a/nmxact/nmble/ble_oic_sesn.go
+++ b/nmxact/nmble/ble_oic_sesn.go
@@ -57,6 +57,7 @@ func NewBleOicSesn(bx *BleXport, cfg sesn.SesnCfg) *BleOicSesn {
SvcUuid: svcUuid,
ReqChrUuid: reqChrUuid,
RspChrUuid: rspChrUuid,
+ Encrypt: cfg.Ble.Encrypt,
RxNmpCb: func(d []byte) { bos.onRxNmp(d) },
DisconnectCb: func(dt BleFsmDisconnectType, p BleDev, e error) {
bos.onDisconnect(dt, p, e)
@@ -245,3 +246,7 @@ func (bos *BleOicSesn) MtuOut() int {
nmp.NMP_HDR_SIZE
return util.IntMin(mtu, BLE_ATT_ATTR_MAX_LEN)
}
+
+func (bos *BleOicSesn) ConnInfo() (BleConnDesc, error) {
+ return bos.bf.connInfo()
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_plain_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_plain_sesn.go b/nmxact/nmble/ble_plain_sesn.go
index 2bcd950..f2048c3 100644
--- a/nmxact/nmble/ble_plain_sesn.go
+++ b/nmxact/nmble/ble_plain_sesn.go
@@ -217,3 +217,7 @@ func (bps *BlePlainSesn) MtuOut() int {
mtu := bps.bf.attMtu - WRITE_CMD_BASE_SZ - nmp.NMP_HDR_SIZE
return util.IntMin(mtu, BLE_ATT_ATTR_MAX_LEN)
}
+
+func (bps *BlePlainSesn) ConnInfo() (BleConnDesc, error) {
+ return bps.bf.connInfo()
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_proto.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_proto.go b/nmxact/nmble/ble_proto.go
index 0bb4d01..24363c7 100644
--- a/nmxact/nmble/ble_proto.go
+++ b/nmxact/nmble/ble_proto.go
@@ -93,7 +93,7 @@ const (
ERR_CODE_HCI_ACL_CONN_EXISTS = 11
ERR_CODE_HCI_CMD_DISALLOWED = 12
ERR_CODE_HCI_CONN_REJ_RESOURCES = 13
- ERR_CODE_HCI_CONN_REJ_SECURITY = 14
+ ERR_CODE_HCI_CONN_REJ_ENC = 14
ERR_CODE_HCI_CONN_REJ_BD_ADDR = 15
ERR_CODE_HCI_CONN_ACCEPT_TMO = 16
ERR_CODE_HCI_UNSUPPORTED = 17
@@ -157,7 +157,7 @@ var HciErrCodeStringMap = map[int]string{
ERR_CODE_HCI_ACL_CONN_EXISTS: "acl conn exists",
ERR_CODE_HCI_CMD_DISALLOWED: "cmd disallowed",
ERR_CODE_HCI_CONN_REJ_RESOURCES: "conn rej resources",
- ERR_CODE_HCI_CONN_REJ_SECURITY: "conn rej security",
+ ERR_CODE_HCI_CONN_REJ_ENC: "conn rej security",
ERR_CODE_HCI_CONN_REJ_BD_ADDR: "conn rej bd addr",
ERR_CODE_HCI_CONN_ACCEPT_TMO: "conn accept tmo",
ERR_CODE_HCI_UNSUPPORTED: "unsupported",
@@ -270,6 +270,7 @@ var MsgTypeStringMap = map[MsgType]string{
MSG_TYPE_SCAN: "scan",
MSG_TYPE_SCAN_CANCEL: "scan_cancel",
MSG_TYPE_SET_PREFERRED_MTU: "set_preferred_mtu",
+ MSG_TYPE_SECURITY_INITIATE: "security_initiate",
MSG_TYPE_CONN_FIND: "conn_find",
MSG_TYPE_RESET: "reset",
@@ -784,6 +785,40 @@ type BleResetRsp struct {
Op MsgOp `json:"op"`
Type MsgType `json:"type"`
Seq BleSeq `json:"seq"`
+
+ // Mandatory
+ Status int `json:"status"`
+}
+
+type BleSecurityInitiateReq struct {
+ // Header
+ Op MsgOp `json:"op"`
+ Type MsgType `json:"type"`
+ Seq BleSeq `json:"seq"`
+
+ // Mandatory
+ ConnHandle uint16 `json:"conn_handle"`
+}
+
+type BleSecurityInitiateRsp struct {
+ // Header
+ Op MsgOp `json:"op"`
+ Type MsgType `json:"type"`
+ Seq BleSeq `json:"seq"`
+
+ // Mandatory
+ Status int `json:"status"`
+}
+
+type BleEncChangeEvt struct {
+ // Header
+ Op MsgOp `json:"op"`
+ Type MsgType `json:"type"`
+ Seq BleSeq `json:"seq"`
+
+ // Mandatory
+ Status int `json:"status"`
+ ConnHandle uint16 `json:"conn_handle"`
}
func ErrCodeToString(e int) string {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_scanner.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_scanner.go b/nmxact/nmble/ble_scanner.go
new file mode 100644
index 0000000..4cdcf07
--- /dev/null
+++ b/nmxact/nmble/ble_scanner.go
@@ -0,0 +1,127 @@
+package nmble
+
+import (
+ "encoding/base64"
+ "fmt"
+
+ log "github.com/Sirupsen/logrus"
+
+ . "mynewt.apache.org/newtmgr/nmxact/bledefs"
+ "mynewt.apache.org/newtmgr/nmxact/omp"
+ "mynewt.apache.org/newtmgr/nmxact/scan"
+ "mynewt.apache.org/newtmgr/nmxact/xact"
+)
+
+// Implements scan.Scanner.
+type BleScanner struct {
+ cfg scan.Cfg
+
+ bx *BleXport
+ reportedDevs map[BleDev][]byte
+ bos *BleOicSesn
+ od *omp.OmpDispatcher
+ enabled bool
+}
+
+func NewBleScanner(bx *BleXport) *BleScanner {
+ return &BleScanner{
+ bx: bx,
+ reportedDevs: map[BleDev][]byte{},
+ }
+}
+
+func (s *BleScanner) scan() (scan.ScanPeer, error) {
+ if err := s.bos.Open(); err != nil {
+ return scan.ScanPeer{}, err
+ }
+ defer s.bos.Close()
+
+ // Now we are connected and paired. Read the peer's hardware ID and report
+ // it upstream.
+
+ desc, err := s.bos.ConnInfo()
+ if err != nil {
+ return scan.ScanPeer{}, err
+ }
+
+ c := xact.NewConfigReadCmd()
+ c.Name = "id/hwid"
+
+ res, err := c.Run(s.bos)
+ if err != nil {
+ return scan.ScanPeer{}, err
+ }
+ if res.Status() != 0 {
+ return scan.ScanPeer{},
+ fmt.Errorf("failed to read hardware ID; NMP status=%d",
+ res.Status())
+ }
+ cres := res.(*xact.ConfigReadResult)
+
+ rawId, err := base64.StdEncoding.DecodeString(cres.Rsp.Val)
+ if err != nil {
+ return scan.ScanPeer{},
+ fmt.Errorf("failed to decode hardware ID; undecoded=%s",
+ cres.Rsp.Val)
+ }
+
+ peer := scan.ScanPeer{
+ HwId: rawId,
+ Opaque: BleDev{
+ AddrType: desc.PeerIdAddrType,
+ Addr: desc.PeerIdAddr,
+ },
+ }
+
+ return peer, nil
+}
+
+func (s *BleScanner) Start(cfg scan.Cfg) error {
+ if s.enabled {
+ return fmt.Errorf("Attempt to start BLE scanner twice")
+ }
+
+ // Wrap predicate with logic that discards duplicates.
+ innerPred := cfg.SesnCfg.Ble.PeerSpec.ScanPred
+ cfg.SesnCfg.Ble.PeerSpec.ScanPred = func(adv BleAdvReport) bool {
+ // Filter devices that have already been reported.
+ if s.reportedDevs[adv.Sender] != nil {
+ return false
+ }
+ return innerPred(adv)
+ }
+
+ session, err := s.bx.BuildSesn(cfg.SesnCfg)
+ if err != nil {
+ return err
+ }
+
+ s.enabled = true
+ s.cfg = cfg
+ s.bos = session.(*BleOicSesn)
+
+ // Start background scanning.
+ go func() {
+ for s.enabled {
+ p, err := s.scan()
+ if err != nil {
+ log.Debugf("Scan error: %s", err.Error())
+ } else {
+ s.reportedDevs[p.Opaque.(BleDev)] = p.HwId
+ s.cfg.ScanCb(p)
+ }
+ }
+ }()
+
+ return nil
+}
+
+func (s *BleScanner) Stop() error {
+ if !s.enabled {
+ return fmt.Errorf("Attempt to stop BLE scanner twice")
+ }
+ s.enabled = false
+
+ s.bos.Close()
+ return nil
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_util.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_util.go b/nmxact/nmble/ble_util.go
index 13a2b8c..fc5fe27 100644
--- a/nmxact/nmble/ble_util.go
+++ b/nmxact/nmble/ble_util.go
@@ -11,12 +11,6 @@ import (
"mynewt.apache.org/newtmgr/nmxact/nmxutil"
)
-const NmpPlainSvcUuid = "8D53DC1D-1DB7-4CD3-868B-8A527460AA84"
-const NmpPlainChrUuid = "DA2E7828-FBCE-4E01-AE9E-261174997C48"
-const NmpOicSvcUuid = "ADE3D529-C784-4F63-A987-EB69F70EE816"
-const NmpOicReqChrUuid = "AD7B334F-4637-4B86-90B6-9D787F03D218"
-const NmpOicRspChrUuid = "E9241982-4580-42C4-8831-95048216B256"
-
const WRITE_CMD_BASE_SZ = 3
const NOTIFY_CMD_BASE_SZ = 3
@@ -251,6 +245,14 @@ func NewResetReq() *BleResetReq {
}
}
+func NewBleSecurityInitiateReq() *BleSecurityInitiateReq {
+ return &BleSecurityInitiateReq{
+ Op: MSG_OP_REQ,
+ Type: MSG_TYPE_SECURITY_INITIATE,
+ Seq: NextSeq(),
+ }
+}
+
func ConnFindXact(x *BleXport, connHandle uint16) (BleConnDesc, error) {
r := NewBleConnFindReq()
r.ConnHandle = connHandle
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/ble_xport.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_xport.go b/nmxact/nmble/ble_xport.go
index 0c2fe80..fdaf07c 100644
--- a/nmxact/nmble/ble_xport.go
+++ b/nmxact/nmble/ble_xport.go
@@ -12,6 +12,7 @@ import (
"mynewt.apache.org/newt/util/unixchild"
. "mynewt.apache.org/newtmgr/nmxact/bledefs"
"mynewt.apache.org/newtmgr/nmxact/nmxutil"
+ "mynewt.apache.org/newtmgr/nmxact/scan"
"mynewt.apache.org/newtmgr/nmxact/sesn"
)
@@ -94,6 +95,7 @@ type BleXport struct {
master nmxutil.SingleResource
randAddr *BleAddr
mtx sync.Mutex
+ scanner *BleScanner
cfg XportCfg
}
@@ -123,6 +125,14 @@ func (bx *BleXport) createUnixChild() {
bx.client = unixchild.New(config)
}
+func (bx *BleXport) BuildScanner() (scan.Scanner, error) {
+ if bx.scanner == nil {
+ bx.scanner = NewBleScanner(bx)
+ }
+
+ return bx.scanner, nil
+}
+
func (bx *BleXport) BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error) {
switch cfg.MgmtProto {
case sesn.MGMT_PROTO_NMP:
@@ -533,10 +543,14 @@ func (bx *BleXport) RspTimeout() time.Duration {
return bx.cfg.BlehostdRspTimeout
}
-func (bx *BleXport) AcquireMaster() error {
- return bx.master.Acquire()
+func (bx *BleXport) AcquireMaster(token interface{}) error {
+ return bx.master.Acquire(token)
}
func (bx *BleXport) ReleaseMaster() {
bx.master.Release()
}
+
+func (bx *BleXport) StopWaitingForMaster(token interface{}, err error) {
+ bx.master.StopWaiting(token, err)
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmble/dispatch.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/dispatch.go b/nmxact/nmble/dispatch.go
index c9f17ec..9225292 100644
--- a/nmxact/nmble/dispatch.go
+++ b/nmxact/nmble/dispatch.go
@@ -84,23 +84,24 @@ type BleDispatcher struct {
type msgCtor func() BleMsg
-func errRspCtor() BleMsg { return &BleErrRsp{} }
-func syncRspCtor() BleMsg { return &BleSyncRsp{} }
-func connectRspCtor() BleMsg { return &BleConnectRsp{} }
-func terminateRspCtor() BleMsg { return &BleTerminateRsp{} }
-func discSvcUuidRspCtor() BleMsg { return &BleDiscSvcUuidRsp{} }
-func discAllChrsRspCtor() BleMsg { return &BleDiscAllChrsRsp{} }
-func discChrUuidRspCtor() BleMsg { return &BleDiscChrUuidRsp{} }
-func writeCmdRspCtor() BleMsg { return &BleWriteCmdRsp{} }
-func exchangeMtuRspCtor() BleMsg { return &BleExchangeMtuRsp{} }
-func genRandAddrRspCtor() BleMsg { return &BleGenRandAddrRsp{} }
-func setRandAddrRspCtor() BleMsg { return &BleSetRandAddrRsp{} }
-func connCancelRspCtor() BleMsg { return &BleConnCancelRsp{} }
-func scanRspCtor() BleMsg { return &BleScanRsp{} }
-func scanCancelRspCtor() BleMsg { return &BleScanCancelRsp{} }
-func setPreferredMtuRspCtor() BleMsg { return &BleSetPreferredMtuRsp{} }
-func connFindRspCtor() BleMsg { return &BleConnFindRsp{} }
-func resetRspCtor() BleMsg { return &BleResetRsp{} }
+func errRspCtor() BleMsg { return &BleErrRsp{} }
+func syncRspCtor() BleMsg { return &BleSyncRsp{} }
+func connectRspCtor() BleMsg { return &BleConnectRsp{} }
+func terminateRspCtor() BleMsg { return &BleTerminateRsp{} }
+func discSvcUuidRspCtor() BleMsg { return &BleDiscSvcUuidRsp{} }
+func discAllChrsRspCtor() BleMsg { return &BleDiscAllChrsRsp{} }
+func discChrUuidRspCtor() BleMsg { return &BleDiscChrUuidRsp{} }
+func writeCmdRspCtor() BleMsg { return &BleWriteCmdRsp{} }
+func exchangeMtuRspCtor() BleMsg { return &BleExchangeMtuRsp{} }
+func genRandAddrRspCtor() BleMsg { return &BleGenRandAddrRsp{} }
+func setRandAddrRspCtor() BleMsg { return &BleSetRandAddrRsp{} }
+func connCancelRspCtor() BleMsg { return &BleConnCancelRsp{} }
+func scanRspCtor() BleMsg { return &BleScanRsp{} }
+func scanCancelRspCtor() BleMsg { return &BleScanCancelRsp{} }
+func setPreferredMtuRspCtor() BleMsg { return &BleSetPreferredMtuRsp{} }
+func securityInitiateRspCtor() BleMsg { return &BleSecurityInitiateRsp{} }
+func connFindRspCtor() BleMsg { return &BleConnFindRsp{} }
+func resetRspCtor() BleMsg { return &BleResetRsp{} }
func syncEvtCtor() BleMsg { return &BleSyncEvt{} }
func connectEvtCtor() BleMsg { return &BleConnectEvt{} }
@@ -111,6 +112,7 @@ func notifyRxEvtCtor() BleMsg { return &BleNotifyRxEvt{} }
func mtuChangeEvtCtor() BleMsg { return &BleMtuChangeEvt{} }
func scanEvtCtor() BleMsg { return &BleScanEvt{} }
func scanTmoEvtCtor() BleMsg { return &BleScanTmoEvt{} }
+func encChangeEvtCtor() BleMsg { return &BleEncChangeEvt{} }
var msgCtorMap = map[OpTypePair]msgCtor{
{MSG_OP_RSP, MSG_TYPE_ERR}: errRspCtor,
@@ -128,6 +130,7 @@ var msgCtorMap = map[OpTypePair]msgCtor{
{MSG_OP_RSP, MSG_TYPE_SCAN}: scanRspCtor,
{MSG_OP_RSP, MSG_TYPE_SCAN_CANCEL}: scanCancelRspCtor,
{MSG_OP_RSP, MSG_TYPE_SET_PREFERRED_MTU}: setPreferredMtuRspCtor,
+ {MSG_OP_RSP, MSG_TYPE_SECURITY_INITIATE}: securityInitiateRspCtor,
{MSG_OP_RSP, MSG_TYPE_CONN_FIND}: connFindRspCtor,
{MSG_OP_RSP, MSG_TYPE_RESET}: resetRspCtor,
@@ -140,6 +143,7 @@ var msgCtorMap = map[OpTypePair]msgCtor{
{MSG_OP_EVT, MSG_TYPE_MTU_CHANGE_EVT}: mtuChangeEvtCtor,
{MSG_OP_EVT, MSG_TYPE_SCAN_EVT}: scanEvtCtor,
{MSG_OP_EVT, MSG_TYPE_SCAN_TMO_EVT}: scanTmoEvtCtor,
+ {MSG_OP_EVT, MSG_TYPE_ENC_CHANGE_EVT}: encChangeEvtCtor,
}
func NewBleDispatcher() *BleDispatcher {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmserial/serial_xport.go
----------------------------------------------------------------------
diff --git a/nmxact/nmserial/serial_xport.go b/nmxact/nmserial/serial_xport.go
index 37f991f..a8c0c71 100644
--- a/nmxact/nmserial/serial_xport.go
+++ b/nmxact/nmserial/serial_xport.go
@@ -14,6 +14,7 @@ import (
"mynewt.apache.org/newt/util"
"mynewt.apache.org/newtmgr/nmxact/nmxutil"
+ "mynewt.apache.org/newtmgr/nmxact/scan"
"mynewt.apache.org/newtmgr/nmxact/sesn"
)
@@ -56,6 +57,10 @@ func (sx *SerialXport) BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error) {
}
}
+func (sx *SerialXport) BuildScanner() (scan.Scanner, error) {
+ return nil, fmt.Errorf("Attempt to build serial scanner")
+}
+
func (sx *SerialXport) Start() error {
c := &serial.Config{
Name: sx.cfg.DevPath,
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/nmxutil/nmxutil.go
----------------------------------------------------------------------
diff --git a/nmxact/nmxutil/nmxutil.go b/nmxact/nmxutil/nmxutil.go
index 707b1bc..257d6b5 100644
--- a/nmxact/nmxutil/nmxutil.go
+++ b/nmxact/nmxutil/nmxutil.go
@@ -1,6 +1,7 @@
package nmxutil
import (
+ "fmt"
"math/rand"
"os"
"sync"
@@ -40,19 +41,22 @@ func NextNmpSeq() uint8 {
return val
}
+type SRWaiter struct {
+ c chan error
+ token interface{}
+}
+
type SingleResource struct {
acquired bool
- waitQueue [](chan error)
+ waitQueue []SRWaiter
mtx sync.Mutex
}
func NewSingleResource() SingleResource {
- return SingleResource{
- waitQueue: [](chan error){},
- }
+ return SingleResource{}
}
-func (s *SingleResource) Acquire() error {
+func (s *SingleResource) Acquire(token interface{}) error {
s.mtx.Lock()
if !s.acquired {
@@ -61,12 +65,17 @@ func (s *SingleResource) Acquire() error {
return nil
}
- w := make(chan error)
+ // XXX: Verify no duplicates.
+
+ w := SRWaiter{
+ c: make(chan error),
+ token: token,
+ }
s.waitQueue = append(s.waitQueue, w)
s.mtx.Unlock()
- err := <-w
+ err := <-w.c
if err != nil {
return err
}
@@ -94,7 +103,19 @@ func (s *SingleResource) Release() {
s.mtx.Unlock()
- w <- nil
+ w.c <- nil
+}
+
+func (s *SingleResource) StopWaiting(token interface{}, err error) {
+ s.mtx.Lock()
+ defer s.mtx.Unlock()
+
+ for _, w := range s.waitQueue {
+ if w.token == token {
+ w.c <- err
+ return
+ }
+ }
}
func (s *SingleResource) Abort(err error) {
@@ -102,9 +123,9 @@ func (s *SingleResource) Abort(err error) {
defer s.mtx.Unlock()
for _, w := range s.waitQueue {
- w <- err
+ w.c <- err
}
- s.waitQueue = [](chan error){}
+ s.waitQueue = nil
}
type ErrLessFn func(a error, b error) bool
@@ -122,6 +143,7 @@ type ErrFunnel struct {
curErr error
errTimer *time.Timer
started bool
+ waiters [](chan error)
}
func (f *ErrFunnel) Start() {
@@ -175,8 +197,13 @@ func (f *ErrFunnel) Reset() {
func (f *ErrFunnel) timerExp() {
f.mtx.Lock()
+
err := f.curErr
f.curErr = nil
+
+ waiters := f.waiters
+ f.waiters = nil
+
f.mtx.Unlock()
if err == nil {
@@ -184,4 +211,34 @@ func (f *ErrFunnel) timerExp() {
}
f.ProcCb(err)
+
+ for _, w := range waiters {
+ w <- err
+ }
+}
+
+func (f *ErrFunnel) Wait() error {
+ var err error
+ var c chan error
+
+ f.mtx.Lock()
+
+ if !f.started {
+ if f.curErr == nil {
+ err = fmt.Errorf("Wait on unstarted ErrFunnel")
+ } else {
+ err = f.curErr
+ }
+ } else {
+ c = make(chan error)
+ f.waiters = append(f.waiters, c)
+ }
+
+ f.mtx.Unlock()
+
+ if err != nil {
+ return err
+ } else {
+ return <-c
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/scan/scan.go
----------------------------------------------------------------------
diff --git a/nmxact/scan/scan.go b/nmxact/scan/scan.go
new file mode 100644
index 0000000..c90546e
--- /dev/null
+++ b/nmxact/scan/scan.go
@@ -0,0 +1,48 @@
+package scan
+
+import (
+ "mynewt.apache.org/newtmgr/nmxact/bledefs"
+ "mynewt.apache.org/newtmgr/nmxact/sesn"
+)
+
+type ScanPeer struct {
+ HwId []byte
+ Opaque interface{}
+}
+
+type ScanFn func(peer ScanPeer)
+
+type Cfg struct {
+ ScanCb ScanFn
+ SesnCfg sesn.SesnCfg
+}
+
+type Scanner interface {
+ Start(cfg Cfg) error
+ Stop() error
+}
+
+func BleOmpScanCfg(ScanCb ScanFn) Cfg {
+ sc := sesn.NewSesnCfg()
+ sc.MgmtProto = sesn.MGMT_PROTO_OMP
+ sc.Ble.OwnAddrType = bledefs.BLE_ADDR_TYPE_RANDOM
+ sc.Ble.Encrypt = bledefs.BLE_ENCRYPT_PRIV_ONLY
+ sc.Ble.PeerSpec = sesn.BlePeerSpec{
+ ScanPred: func(adv bledefs.BleAdvReport) bool {
+ for _, u := range adv.Uuids16 {
+ if u == bledefs.OmpSvcUuid {
+ return true
+ }
+ }
+
+ return false
+ },
+ }
+
+ cfg := Cfg{
+ ScanCb: ScanCb,
+ SesnCfg: sc,
+ }
+
+ return cfg
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/sesn/sesn_cfg.go
----------------------------------------------------------------------
diff --git a/nmxact/sesn/sesn_cfg.go b/nmxact/sesn/sesn_cfg.go
index 60cdc81..0022640 100644
--- a/nmxact/sesn/sesn_cfg.go
+++ b/nmxact/sesn/sesn_cfg.go
@@ -47,6 +47,8 @@ type SesnCfgBle struct {
ConnTries int
CloseTimeout time.Duration
OnCloseCb BleOnCloseFn
+
+ Encrypt bledefs.BleEncryptWhen
}
type SesnCfg struct {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/822cea97/nmxact/xport/xport.go
----------------------------------------------------------------------
diff --git a/nmxact/xport/xport.go b/nmxact/xport/xport.go
index 85ef2b2..ec8a499 100644
--- a/nmxact/xport/xport.go
+++ b/nmxact/xport/xport.go
@@ -1,6 +1,7 @@
package xport
import (
+ "mynewt.apache.org/newtmgr/nmxact/scan"
"mynewt.apache.org/newtmgr/nmxact/sesn"
)
@@ -9,7 +10,9 @@ type RxFn func(data []byte)
type Xport interface {
Start() error
Stop() error
+
BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error)
+ BuildScanner() (scan.Scanner, error)
Tx(data []byte) error
}