Repository: incubator-mynewt-newtmgr
Updated Branches:
  refs/heads/master 5af109bf9 -> 99af734d9


nmxact - separate connect and discover procedures.


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/99af734d
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/99af734d
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/99af734d

Branch: refs/heads/master
Commit: 99af734d98bba36b204dd893a529257afc4cdef6
Parents: 5af109b
Author: Christopher Collins <ccoll...@apache.org>
Authored: Fri May 19 18:03:00 2017 -0700
Committer: Christopher Collins <ccoll...@apache.org>
Committed: Fri May 19 18:04:35 2017 -0700

----------------------------------------------------------------------
 newtmgr/cli/common.go                 |  25 ++++-
 newtmgr/config/ble_config.go          |  24 ++++-
 nmxact/bledefs/bledefs.go             |   1 +
 nmxact/example/ble_loop/ble_loop.go   |  18 +++-
 nmxact/example/ble_plain/ble_plain.go |  18 +++-
 nmxact/example/ble_scan/ble_scan.go   |   5 +-
 nmxact/nmble/ble_act.go               |   5 +-
 nmxact/nmble/ble_fsm.go               | 160 +++++------------------------
 nmxact/nmble/ble_oic_sesn.go          |  10 +-
 nmxact/nmble/ble_plain_sesn.go        |   9 +-
 nmxact/nmble/ble_scanner.go           | 130 +++++++++++++++--------
 nmxact/nmble/ble_util.go              |  14 +++
 nmxact/nmble/discover.go              | 142 +++++++++++++++++++++++++
 nmxact/scan/scan.go                   |  37 ++++---
 nmxact/sesn/sesn_cfg.go               |  42 +++-----
 15 files changed, 394 insertions(+), 246 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/newtmgr/cli/common.go
----------------------------------------------------------------------
diff --git a/newtmgr/cli/common.go b/newtmgr/cli/common.go
index da3c348..0d11478 100644
--- a/newtmgr/cli/common.go
+++ b/newtmgr/cli/common.go
@@ -22,12 +22,13 @@ package cli
 import (
        "fmt"
 
+       "mynewt.apache.org/newt/util"
        "mynewt.apache.org/newtmgr/newtmgr/config"
        "mynewt.apache.org/newtmgr/newtmgr/nmutil"
+       "mynewt.apache.org/newtmgr/nmxact/nmble"
        "mynewt.apache.org/newtmgr/nmxact/nmserial"
        "mynewt.apache.org/newtmgr/nmxact/sesn"
        "mynewt.apache.org/newtmgr/nmxact/xport"
-       "mynewt.apache.org/newt/util"
 )
 
 var globalSesn sesn.Sesn
@@ -109,8 +110,17 @@ func buildSesnCfg() (sesn.SesnCfg, error) {
                        return sc, err
                }
 
+               x, err := GetXport()
+               if err != nil {
+                       return sc, err
+               }
+               bx := x.(*nmble.BleXport)
+
                sc.MgmtProto = sesn.MGMT_PROTO_NMP
-               config.FillSesnCfg(bc, &sc)
+               if err := config.FillSesnCfg(bx, bc, &sc); err != nil {
+                       return sc, err
+               }
+
                return sc, nil
 
        case config.CONN_TYPE_BLE_OIC:
@@ -119,8 +129,17 @@ func buildSesnCfg() (sesn.SesnCfg, error) {
                        return sc, err
                }
 
+               x, err := GetXport()
+               if err != nil {
+                       return sc, err
+               }
+               bx := x.(*nmble.BleXport)
+
                sc.MgmtProto = sesn.MGMT_PROTO_OMP
-               config.FillSesnCfg(bc, &sc)
+               if err := config.FillSesnCfg(bx, bc, &sc); err != nil {
+                       return sc, err
+               }
+
                return sc, nil
 
        default:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/newtmgr/config/ble_config.go
----------------------------------------------------------------------
diff --git a/newtmgr/config/ble_config.go b/newtmgr/config/ble_config.go
index d501a71..52eb4f2 100644
--- a/newtmgr/config/ble_config.go
+++ b/newtmgr/config/ble_config.go
@@ -104,7 +104,7 @@ func ParseBleConnString(cs string) (*BleConfig, error) {
        return bc, nil
 }
 
-func FillSesnCfg(bc *BleConfig, sc *sesn.SesnCfg) {
+func FillSesnCfg(bx *nmble.BleXport, bc *BleConfig, sc *sesn.SesnCfg) error {
        sc.Ble.OwnAddrType = bc.OwnAddrType
 
        if nmutil.DeviceName != "" {
@@ -112,16 +112,32 @@ func FillSesnCfg(bc *BleConfig, sc *sesn.SesnCfg) {
        }
 
        if bc.PeerName != "" {
-               sc.Ble.PeerSpec = sesn.BlePeerSpecName(bc.PeerName)
+               scanPred := func(r bledefs.BleAdvReport) bool {
+                       return r.Name == bc.PeerName
+               }
+               dev, err := nmble.DiscoverDevice(
+                       bx, bc.OwnAddrType, 15*time.Second, scanPred)
+
+               if err != nil {
+                       return err
+               }
+               if dev == nil {
+                       return util.FmtNewtError(
+                               "Unable to discover device with name \"%s\"", 
bc.PeerName)
+               }
+
+               sc.PeerSpec.Ble = *dev
        } else {
-               sc.Ble.PeerSpec = sesn.BlePeerSpecDev(bledefs.BleDev{
+               sc.PeerSpec.Ble = bledefs.BleDev{
                        AddrType: bc.PeerAddrType,
                        Addr:     bc.PeerAddr,
-               })
+               }
        }
 
        // We don't need to stick around until a connection closes.
        sc.Ble.CloseTimeout = 10000 * time.Millisecond
+
+       return nil
 }
 
 func BuildBleXport(bc *BleConfig) (*nmble.BleXport, error) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/bledefs/bledefs.go
----------------------------------------------------------------------
diff --git a/nmxact/bledefs/bledefs.go b/nmxact/bledefs/bledefs.go
index e6f620e..4e850a5 100644
--- a/nmxact/bledefs/bledefs.go
+++ b/nmxact/bledefs/bledefs.go
@@ -398,6 +398,7 @@ type BleAdvReport struct {
        MfgData             []byte    // false if not present
 }
 
+type BleAdvRptFn func(r BleAdvReport)
 type BleAdvPredicate func(adv BleAdvReport) bool
 
 type BleConnDesc struct {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/example/ble_loop/ble_loop.go
----------------------------------------------------------------------
diff --git a/nmxact/example/ble_loop/ble_loop.go 
b/nmxact/example/ble_loop/ble_loop.go
index 7c6140a..7a930a9 100644
--- a/nmxact/example/ble_loop/ble_loop.go
+++ b/nmxact/example/ble_loop/ble_loop.go
@@ -24,6 +24,7 @@ import (
        "os"
        "os/signal"
        "syscall"
+       "time"
 
        "mynewt.apache.org/newtmgr/nmxact/bledefs"
        "mynewt.apache.org/newtmgr/nmxact/nmble"
@@ -78,14 +79,27 @@ func main() {
        }
        defer x.Stop()
 
+       // Find a device to connect to:
+       //     * Peer has name "nimble-bleprph"
+       //     * We use a random address.
+       dev, err := nmble.DiscoverDeviceWithName(
+               x, bledefs.BLE_ADDR_TYPE_RANDOM, 10*time.Second, 
"nimble-bleprph")
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "error discovering device: %s\n", 
err.Error())
+               os.Exit(1)
+       }
+       if dev == nil {
+               fmt.Fprintf(os.Stderr, "couldn't find device")
+               os.Exit(1)
+       }
+
        // Prepare a BLE session:
        //     * Plain NMP (not tunnelled over OIC).
        //     * We use a random address.
-       //     * Peer has name "nimble-bleprph".
        sc := sesn.NewSesnCfg()
        sc.MgmtProto = sesn.MGMT_PROTO_NMP
        sc.Ble.OwnAddrType = bledefs.BLE_ADDR_TYPE_RANDOM
-       sc.Ble.PeerSpec = sesn.BlePeerSpecName("nimble-bleprph")
+       sc.PeerSpec.Ble = *dev
 
        s, err := x.BuildSesn(sc)
        if err != nil {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/example/ble_plain/ble_plain.go
----------------------------------------------------------------------
diff --git a/nmxact/example/ble_plain/ble_plain.go 
b/nmxact/example/ble_plain/ble_plain.go
index a91285c..3872dec 100644
--- a/nmxact/example/ble_plain/ble_plain.go
+++ b/nmxact/example/ble_plain/ble_plain.go
@@ -22,6 +22,7 @@ package main
 import (
        "fmt"
        "os"
+       "time"
 
        "mynewt.apache.org/newtmgr/nmxact/bledefs"
        "mynewt.apache.org/newtmgr/nmxact/nmble"
@@ -51,14 +52,27 @@ func main() {
        }
        defer x.Stop()
 
+       // Find a device to connect to:
+       //     * Peer has name "nimble-bleprph"
+       //     * We use a random address.
+       dev, err := nmble.DiscoverDeviceWithName(
+               x, bledefs.BLE_ADDR_TYPE_RANDOM, 10*time.Second, 
"nimble-bleprph")
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "error discovering device: %s\n", 
err.Error())
+               os.Exit(1)
+       }
+       if dev == nil {
+               fmt.Fprintf(os.Stderr, "couldn't find device")
+               os.Exit(1)
+       }
+
        // Prepare a BLE session:
        //     * Plain NMP (not tunnelled over OIC).
        //     * We use a random address.
-       //     * Peer has name "nimble-bleprph".
        sc := sesn.NewSesnCfg()
        sc.MgmtProto = sesn.MGMT_PROTO_NMP
        sc.Ble.OwnAddrType = bledefs.BLE_ADDR_TYPE_RANDOM
-       sc.Ble.PeerSpec = sesn.BlePeerSpecName("nimble-bleprph")
+       sc.PeerSpec.Ble = *dev
 
        s, err := x.BuildSesn(sc)
        if err != nil {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/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
index d9f794c..4ac80e1 100644
--- a/nmxact/example/ble_scan/ble_scan.go
+++ b/nmxact/example/ble_scan/ble_scan.go
@@ -105,6 +105,9 @@ func main() {
 
        for {
                sc := scan.BleOmpScanCfg(scanCb)
+               sc.Ble.ScanPred = func(adv bledefs.BleAdvReport) bool {
+                       return adv.Name == "ccollins"
+               }
                if err := scanner.Start(sc); err != nil {
                        fmt.Fprintf(os.Stderr, "error starting scan: %s\n", 
err.Error())
                        os.Exit(1)
@@ -122,7 +125,7 @@ func main() {
                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))
+               c.PeerSpec = p.PeerSpec
 
                s, err := x.BuildSesn(c)
                if err != nil {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_act.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_act.go b/nmxact/nmble/ble_act.go
index ed129cd..95a6436 100644
--- a/nmxact/nmble/ble_act.go
+++ b/nmxact/nmble/ble_act.go
@@ -285,11 +285,8 @@ func exchangeMtu(x *BleXport, bl *BleListener, r 
*BleExchangeMtuReq) (
        }
 }
 
-type scanSuccessFn func()
-type advRptFn func(r BleAdvReport)
-
 func actScan(x *BleXport, bl *BleListener, r *BleScanReq,
-       abortChan chan struct{}, advRptCb advRptFn) error {
+       abortChan chan struct{}, advRptCb BleAdvRptFn) error {
 
        const rspType = MSG_TYPE_SCAN
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_fsm.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_fsm.go b/nmxact/nmble/ble_fsm.go
index ed7b90b..f8a893a 100644
--- a/nmxact/nmble/ble_fsm.go
+++ b/nmxact/nmble/ble_fsm.go
@@ -14,7 +14,6 @@ import (
        . "mynewt.apache.org/newtmgr/nmxact/bledefs"
        "mynewt.apache.org/newtmgr/nmxact/nmp"
        "mynewt.apache.org/newtmgr/nmxact/nmxutil"
-       "mynewt.apache.org/newtmgr/nmxact/sesn"
 )
 
 var nextId uint32
@@ -29,16 +28,15 @@ type BleSesnState int32
 
 const (
        SESN_STATE_UNCONNECTED     BleSesnState = 0
-       SESN_STATE_SCANNING                     = 1
-       SESN_STATE_CONNECTING                   = 2
-       SESN_STATE_EXCHANGE_MTU                 = 3
-       SESN_STATE_DISCOVER_SVC                 = 4
-       SESN_STATE_DISCOVER_CHR                 = 5
-       SESN_STATE_SECURITY                     = 6
-       SESN_STATE_SUBSCRIBE                    = 7
-       SESN_STATE_DONE                         = 8
-       SESN_STATE_TERMINATING                  = 9
-       SESN_STATE_CONN_CANCELLING              = 10
+       SESN_STATE_CONNECTING                   = 1
+       SESN_STATE_EXCHANGE_MTU                 = 2
+       SESN_STATE_DISCOVER_SVC                 = 3
+       SESN_STATE_DISCOVER_CHR                 = 4
+       SESN_STATE_SECURITY                     = 5
+       SESN_STATE_SUBSCRIBE                    = 6
+       SESN_STATE_DONE                         = 7
+       SESN_STATE_TERMINATING                  = 8
+       SESN_STATE_CONN_CANCELLING              = 9
 )
 
 type BleFsmDisconnectType int
@@ -61,20 +59,19 @@ type BleDisconnectFn func(dt BleFsmDisconnectType, peer 
BleDev, err error)
 type BleFsmParams struct {
        Bx           *BleXport
        OwnAddrType  BleAddrType
-       PeerSpec     sesn.BlePeerSpec
+       PeerDev      BleDev
        ConnTries    int
        SvcUuid      BleUuid
        ReqChrUuid   BleUuid
        RspChrUuid   BleUuid
        RxNmpCb      BleRxNmpFn
        DisconnectCb BleDisconnectFn
-       Encrypt      BleEncryptWhen
+       EncryptWhen  BleEncryptWhen
 }
 
 type BleFsm struct {
        params BleFsmParams
 
-       peerDev    *BleDev
        connHandle uint16
        nmpSvc     *BleSvc
        nmpReqChr  *BleChr
@@ -114,7 +111,8 @@ func NewBleFsm(p BleFsmParams) *BleFsm {
 func (bf *BleFsm) disconnectError(reason int) error {
        str := fmt.Sprintf("BLE peer disconnected; "+
                "reason=\"%s\" (%d) peer=%s handle=%d",
-               ErrCodeToString(reason), reason, bf.peerDev.String(), 
bf.connHandle)
+               ErrCodeToString(reason), reason, bf.params.PeerDev.String(),
+               bf.connHandle)
        return nmxutil.NewBleSesnDisconnectError(reason, str)
 }
 
@@ -269,22 +267,16 @@ func (bf *BleFsm) processErr(err error) {
        // Remember some fields before we clear them.
        dt := calcDisconnectType(bf.getState())
 
-       var peer BleDev
-       if bf.peerDev != nil {
-               peer = *bf.peerDev
-       }
-
        bf.params.Bx.StopWaitingForMaster(bf, err)
        bf.errorAll(err)
 
        bf.setState(SESN_STATE_UNCONNECTED)
-       bf.peerDev = nil
 
        // Wait for all listeners to get removed.
        bf.wg.Wait()
 
        bf.errFunnel.Reset()
-       bf.params.DisconnectCb(dt, peer, err)
+       bf.params.DisconnectCb(dt, bf.params.PeerDev, err)
 }
 
 func (bf *BleFsm) connectListen(seq BleSeq) error {
@@ -312,7 +304,7 @@ func (bf *BleFsm) connectListen(seq BleSeq) error {
                                                str := fmt.Sprintf("BLE 
connection attempt failed; "+
                                                        "status=%s (%d) 
peer=%s",
                                                        
ErrCodeToString(msg.Status), msg.Status,
-                                                       bf.peerDev.String())
+                                                       
bf.params.PeerDev.String())
                                                log.Debugf(str)
                                                err := 
nmxutil.NewBleHostError(msg.Status, str)
                                                bf.connChan <- err
@@ -337,7 +329,7 @@ func (bf *BleFsm) connectListen(seq BleSeq) error {
                                                str := fmt.Sprintf("BLE 
connection attempt failed; "+
                                                        "status=%s (%d) 
peer=%s",
                                                        
ErrCodeToString(msg.Status), msg.Status,
-                                                       bf.peerDev.String())
+                                                       
bf.params.PeerDev.String())
                                                log.Debugf(str)
                                                err := 
nmxutil.NewBleHostError(msg.Status, str)
                                                bf.connChan <- err
@@ -430,8 +422,8 @@ func (bf *BleFsm) nmpRspListen() error {
 func (bf *BleFsm) connect() error {
        r := NewBleConnectReq()
        r.OwnAddrType = bf.params.OwnAddrType
-       r.PeerAddrType = bf.peerDev.AddrType
-       r.PeerAddr = bf.peerDev.Addr
+       r.PeerAddrType = bf.params.PeerDev.AddrType
+       r.PeerAddr = bf.params.PeerDev.Addr
 
        // Initiating a connection requires dedicated master privileges.
        if err := bf.params.Bx.AcquireMaster(bf); err != nil {
@@ -470,68 +462,6 @@ func (bf *BleFsm) connect() error {
        return err
 }
 
-func (bf *BleFsm) scan() error {
-       r := NewBleScanReq()
-       r.OwnAddrType = bf.params.OwnAddrType
-       r.DurationMs = 15000
-       r.FilterPolicy = BLE_SCAN_FILT_NO_WL
-       r.Limited = false
-       r.Passive = false
-       r.FilterDuplicates = true
-
-       // Scanning requires dedicated master privileges.
-       if err := bf.params.Bx.AcquireMaster(bf); err != nil {
-               return err
-       }
-       defer bf.params.Bx.ReleaseMaster()
-
-       bl, err := bf.addBleSeqListener("scan", r.Seq)
-       if err != nil {
-               return err
-       }
-       defer bf.removeBleSeqListener("scan", r.Seq)
-
-       abortChan := make(chan struct{}, 1)
-
-       // This function gets called for each incoming advertisement.
-       advRptCb := func(r BleAdvReport) {
-               // Ask client if we should connect to this advertiser.
-               if bf.params.PeerSpec.ScanPred(r) {
-                       bf.peerDev = &r.Sender
-                       abortChan <- struct{}{}
-               }
-       }
-
-       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 {
-                       log.Errorf("Failed to cancel scan in progress: %s",
-                               err.Error())
-               }
-       }
-
-       return err
-}
-
-func (bf *BleFsm) scanCancel() error {
-       r := NewBleScanCancelReq()
-
-       bl, err := bf.addBleSeqListener("scan-cancel", r.Seq)
-       if err != nil {
-               return err
-       }
-       defer bf.removeBleSeqListener("scan-cancel", r.Seq)
-
-       if err := scanCancel(bf.params.Bx, bl, r); err != nil {
-               return err
-       }
-
-       return nil
-}
-
 func (bf *BleFsm) terminateSetState() error {
        switch bf.getState() {
        case SESN_STATE_UNCONNECTED,
@@ -724,7 +654,7 @@ func (bf *BleFsm) subscribe() error {
 }
 
 func (bf *BleFsm) shouldEncrypt() bool {
-       switch bf.params.Encrypt {
+       switch bf.params.EncryptWhen {
        case BLE_ENCRYPT_NEVER:
                return false
 
@@ -732,56 +662,22 @@ func (bf *BleFsm) shouldEncrypt() bool {
                return true
 
        case BLE_ENCRYPT_PRIV_ONLY:
-               return bf.peerDev.AddrType == BLE_ADDR_TYPE_RPA_PUB ||
-                       bf.peerDev.AddrType == BLE_ADDR_TYPE_RPA_RND
+               return bf.params.PeerDev.AddrType == BLE_ADDR_TYPE_RPA_PUB ||
+                       bf.params.PeerDev.AddrType == BLE_ADDR_TYPE_RPA_RND
 
        default:
                panic(fmt.Sprintf("Invalid BleEncryptWhen value: %d",
-                       bf.params.Encrypt))
+                       bf.params.EncryptWhen))
        }
 }
 
-// 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 {
-       // The peer spec contains one of:
-       //     * Peer address;
-       //     * Predicate function to call during scanning.
-       // If a peer address is specified, fill in the peer field now so the
-       // scanning step can be skipped.  Otherwise, the peer field gets 
populated
-       // during scanning.
-       if bf.params.PeerSpec.ScanPred == nil {
-               bf.peerDev = &bf.params.PeerSpec.Dev
-               return true
-       }
-
-       return false
-}
-
 func (bf *BleFsm) executeState() (bool, error) {
        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
-               // address, or if we have already successfully scanned, we 
initiate
-               // a connection now.  Otherwise, we need to scan to determine 
which
-               // peer meets the specified scan criteria.
-               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.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.setState(SESN_STATE_EXCHANGE_MTU)
+               if err := bf.connect(); err != nil {
+                       return false, err
                }
+               bf.setState(SESN_STATE_EXCHANGE_MTU)
 
        case SESN_STATE_EXCHANGE_MTU:
                if err := bf.exchangeMtu(); err != nil {
@@ -885,10 +781,6 @@ 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
@@ -928,7 +820,7 @@ func (bf *BleFsm) TxNmp(payload []byte, nl *nmp.NmpListener,
                        msg := fmt.Sprintf(
                                "NMP timeout; op=%d group=%d id=%d seq=%d 
peer=%#v",
                                payload[0], payload[4]+payload[5]<<8,
-                               payload[7], payload[6], bf.peerDev)
+                               payload[7], payload[6], bf.params.PeerDev)
 
                        return nil, nmxutil.NewNmpTimeoutError(msg)
                }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_oic_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_oic_sesn.go b/nmxact/nmble/ble_oic_sesn.go
index 6cac7cf..c50f19d 100644
--- a/nmxact/nmble/ble_oic_sesn.go
+++ b/nmxact/nmble/ble_oic_sesn.go
@@ -20,7 +20,7 @@ type BleOicSesn struct {
        nls          map[*nmp.NmpListener]struct{}
        od           *omp.OmpDispatcher
        closeTimeout time.Duration
-       onCloseCb    sesn.BleOnCloseFn
+       onCloseCb    sesn.OnCloseFn
 
        closeChan chan error
        mtx       sync.Mutex
@@ -31,7 +31,7 @@ func NewBleOicSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BleOicSesn {
                nls:          map[*nmp.NmpListener]struct{}{},
                od:           omp.NewOmpDispatcher(),
                closeTimeout: cfg.Ble.CloseTimeout,
-               onCloseCb:    cfg.Ble.OnCloseCb,
+               onCloseCb:    cfg.OnCloseCb,
        }
 
        svcUuid := BleUuid{Uuid16: OmpSvcUuid}
@@ -49,12 +49,12 @@ func NewBleOicSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BleOicSesn {
        bos.bf = NewBleFsm(BleFsmParams{
                Bx:          bx,
                OwnAddrType: cfg.Ble.OwnAddrType,
-               PeerSpec:    cfg.Ble.PeerSpec,
+               PeerDev:     cfg.PeerSpec.Ble,
                ConnTries:   cfg.Ble.ConnTries,
                SvcUuid:     svcUuid,
                ReqChrUuid:  reqChrUuid,
                RspChrUuid:  rspChrUuid,
-               Encrypt:     cfg.Ble.Encrypt,
+               EncryptWhen: cfg.Ble.EncryptWhen,
                RxNmpCb:     func(d []byte) { bos.onRxNmp(d) },
                DisconnectCb: func(dt BleFsmDisconnectType, p BleDev, e error) {
                        bos.onDisconnect(dt, p, e)
@@ -198,7 +198,7 @@ func (bos *BleOicSesn) onDisconnect(dt 
BleFsmDisconnectType, peer BleDev,
        // Only execute client's disconnect callback if the disconnect was
        // unsolicited and the session was fully open.
        if dt == FSM_DISCONNECT_TYPE_OPENED && bos.onCloseCb != nil {
-               bos.onCloseCb(bos, peer, err)
+               bos.onCloseCb(bos, err)
        }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_plain_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_plain_sesn.go b/nmxact/nmble/ble_plain_sesn.go
index f2048c3..ac56dee 100644
--- a/nmxact/nmble/ble_plain_sesn.go
+++ b/nmxact/nmble/ble_plain_sesn.go
@@ -19,7 +19,7 @@ type BlePlainSesn struct {
        nls          map[*nmp.NmpListener]struct{}
        nd           *nmp.NmpDispatcher
        closeTimeout time.Duration
-       onCloseCb    sesn.BleOnCloseFn
+       onCloseCb    sesn.OnCloseFn
 
        closeChan chan error
        mtx       sync.Mutex
@@ -30,7 +30,7 @@ func NewBlePlainSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BlePlainSesn {
                nls:          map[*nmp.NmpListener]struct{}{},
                nd:           nmp.NewNmpDispatcher(),
                closeTimeout: cfg.Ble.CloseTimeout,
-               onCloseCb:    cfg.Ble.OnCloseCb,
+               onCloseCb:    cfg.OnCloseCb,
        }
 
        svcUuid, err := ParseUuid(NmpPlainSvcUuid)
@@ -46,11 +46,12 @@ func NewBlePlainSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BlePlainSesn {
        bps.bf = NewBleFsm(BleFsmParams{
                Bx:          bx,
                OwnAddrType: cfg.Ble.OwnAddrType,
-               PeerSpec:    cfg.Ble.PeerSpec,
+               PeerDev:     cfg.PeerSpec.Ble,
                ConnTries:   cfg.Ble.ConnTries,
                SvcUuid:     svcUuid,
                ReqChrUuid:  chrUuid,
                RspChrUuid:  chrUuid,
+               EncryptWhen: cfg.Ble.EncryptWhen,
                RxNmpCb:     func(d []byte) { bps.onRxNmp(d) },
                DisconnectCb: func(dt BleFsmDisconnectType, p BleDev, e error) {
                        bps.onDisconnect(dt, p, e)
@@ -178,7 +179,7 @@ func (bps *BlePlainSesn) onDisconnect(dt 
BleFsmDisconnectType, peer BleDev,
        // Only execute client's disconnect callback if the disconnect was
        // unsolicited and the session was fully open.
        if dt == FSM_DISCONNECT_TYPE_OPENED && bps.onCloseCb != nil {
-               bps.onCloseCb(bps, peer, err)
+               bps.onCloseCb(bps, err)
        }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_scanner.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_scanner.go b/nmxact/nmble/ble_scanner.go
index 28605df..338b7cd 100644
--- a/nmxact/nmble/ble_scanner.go
+++ b/nmxact/nmble/ble_scanner.go
@@ -1,16 +1,16 @@
 package nmble
 
 import (
-       "bytes"
-       "encoding/base64"
        "fmt"
        "sync"
+       "time"
 
        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/sesn"
        "mynewt.apache.org/newtmgr/nmxact/xact"
 )
 
@@ -19,7 +19,8 @@ type BleScanner struct {
        cfg scan.Cfg
 
        bx           *BleXport
-       reportedDevs map[BleDev][]byte
+       discoverer   *Discoverer
+       reportedDevs map[BleDev]string
        bos          *BleOicSesn
        od           *omp.OmpDispatcher
        enabled      bool
@@ -31,54 +32,101 @@ type BleScanner struct {
 func NewBleScanner(bx *BleXport) *BleScanner {
        return &BleScanner{
                bx:           bx,
-               reportedDevs: map[BleDev][]byte{},
+               reportedDevs: map[BleDev]string{},
        }
 }
 
-func (s *BleScanner) scan() (scan.ScanPeer, error) {
-       if err := s.bos.Open(); err != nil {
-               return scan.ScanPeer{}, err
+func (s *BleScanner) discover() (*BleDev, error) {
+       s.discoverer = NewDiscoverer(DiscovererParams{
+               Bx:          s.bx,
+               OwnAddrType: s.cfg.SesnCfg.Ble.OwnAddrType,
+               Passive:     false,
+               Duration:    15 * time.Second,
+       })
+       defer func() { s.discoverer = nil }()
+
+       var dev *BleDev
+       advRptCb := func(r BleAdvReport) {
+               if s.cfg.Ble.ScanPred(r) {
+                       dev = &r.Sender
+                       s.discoverer.Stop()
+               }
+       }
+       if err := s.discoverer.Start(advRptCb); err != nil {
+               return nil, err
        }
-       defer s.bos.Close()
 
-       // Now we are connected (and paired if required).  Read the peer's 
hardware
-       // ID and report it upstream.
+       return dev, nil
+}
 
-       desc, err := s.bos.ConnInfo()
+func (s *BleScanner) connect(dev BleDev) error {
+       s.cfg.SesnCfg.PeerSpec.Ble = dev
+       session, err := s.bx.BuildSesn(s.cfg.SesnCfg)
        if err != nil {
-               return scan.ScanPeer{}, err
+               return err
+       }
+       s.bos = session.(*BleOicSesn)
+
+       if err := s.bos.Open(); err != nil {
+               return err
        }
 
+       return nil
+}
+
+func (s *BleScanner) readHwId() (string, error) {
        c := xact.NewConfigReadCmd()
        c.Name = "id/hwid"
 
        res, err := c.Run(s.bos)
        if err != nil {
-               return scan.ScanPeer{}, err
+               return "", err
        }
        if res.Status() != 0 {
-               return scan.ScanPeer{},
-                       fmt.Errorf("failed to read hardware ID; NMP status=%d",
+               return "",
+                       fmt.Errorf("failed to read hardware ID; NMP 
status=%discoverer",
                                res.Status())
        }
        cres := res.(*xact.ConfigReadResult)
+       return cres.Rsp.Val, nil
+}
 
-       rawId, err := base64.StdEncoding.DecodeString(cres.Rsp.Val)
+func (s *BleScanner) scan() (*scan.ScanPeer, error) {
+       // Discover the first device which matches the specified predicate.
+       dev, err := s.discover()
        if err != nil {
-               return scan.ScanPeer{},
-                       fmt.Errorf("failed to decode hardware ID; undecoded=%s",
-                               cres.Rsp.Val)
+               return nil, err
+       }
+       if dev == nil {
+               return nil, nil
+       }
+
+       s.connect(*dev)
+       defer s.bos.Close()
+
+       // Now we are connected (and paired if required).  Read the peer's 
hardware
+       // ID and report it upstream.
+       hwId, err := s.readHwId()
+       if err != nil {
+               return nil, err
+       }
+
+       desc, err := s.bos.ConnInfo()
+       if err != nil {
+               return nil, err
        }
 
        peer := scan.ScanPeer{
-               HwId: rawId,
-               Opaque: BleDev{
-                       AddrType: desc.PeerIdAddrType,
-                       Addr:     desc.PeerIdAddr,
+               HwId: hwId,
+               PeerSpec: sesn.PeerSpec{
+                       Ble: BleDev{
+                               AddrType: desc.PeerIdAddrType,
+                               Addr:     desc.PeerIdAddr,
+                       },
                },
        }
 
-       return peer, nil
+       return &peer, nil
 }
 
 func (s *BleScanner) Start(cfg scan.Cfg) error {
@@ -87,11 +135,11 @@ func (s *BleScanner) Start(cfg scan.Cfg) error {
        }
 
        // Wrap predicate with logic that discards duplicates.
-       innerPred := cfg.SesnCfg.Ble.PeerSpec.ScanPred
-       cfg.SesnCfg.Ble.PeerSpec.ScanPred = func(adv BleAdvReport) bool {
+       innerPred := cfg.Ble.ScanPred
+       cfg.Ble.ScanPred = func(adv BleAdvReport) bool {
                // Filter devices that have already been reported.
                s.devMapMtx.Lock()
-               seen := s.reportedDevs[adv.Sender] != nil
+               seen := s.reportedDevs[adv.Sender] != ""
                s.devMapMtx.Unlock()
 
                if seen {
@@ -101,14 +149,8 @@ func (s *BleScanner) Start(cfg scan.Cfg) error {
                }
        }
 
-       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() {
@@ -116,12 +158,12 @@ func (s *BleScanner) Start(cfg scan.Cfg) error {
                        p, err := s.scan()
                        if err != nil {
                                log.Debugf("Scan error: %s", err.Error())
-                       } else {
+                       } else if p != nil {
                                s.devMapMtx.Lock()
-                               s.reportedDevs[p.Opaque.(BleDev)] = p.HwId
+                               s.reportedDevs[p.PeerSpec.Ble] = p.HwId
                                s.devMapMtx.Unlock()
 
-                               s.cfg.ScanCb(p)
+                               s.cfg.ScanCb(*p)
                        }
                }
        }()
@@ -135,6 +177,10 @@ func (s *BleScanner) Stop() error {
        }
        s.enabled = false
 
+       discoverer := s.discoverer
+       if discoverer != nil {
+               discoverer.Stop()
+       }
        s.bos.Close()
        return nil
 }
@@ -142,13 +188,13 @@ func (s *BleScanner) Stop() error {
 // @return                      true if the specified device was found and
 //                                  forgetten;
 //                              false if the specified device is unknown.
-func (s *BleScanner) ForgetDevice(hwid []byte) bool {
+func (s *BleScanner) ForgetDevice(hwId string) bool {
        s.devMapMtx.Lock()
        defer s.devMapMtx.Unlock()
 
-       for d, h := range s.reportedDevs {
-               if bytes.Compare(h, hwid) == 0 {
-                       delete(s.reportedDevs, d)
+       for discoverer, h := range s.reportedDevs {
+               if h == hwId {
+                       delete(s.reportedDevs, discoverer)
                        return true
                }
        }
@@ -160,7 +206,7 @@ func (s *BleScanner) ForgetAllDevices() {
        s.devMapMtx.Lock()
        defer s.devMapMtx.Unlock()
 
-       for d, _ := range s.reportedDevs {
-               delete(s.reportedDevs, d)
+       for discoverer, _ := range s.reportedDevs {
+               delete(s.reportedDevs, discoverer)
        }
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/ble_util.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_util.go b/nmxact/nmble/ble_util.go
index fc5fe27..8dccb39 100644
--- a/nmxact/nmble/ble_util.go
+++ b/nmxact/nmble/ble_util.go
@@ -4,6 +4,7 @@ import (
        "fmt"
        "runtime"
        "sync"
+       "time"
 
        log "github.com/Sirupsen/logrus"
 
@@ -349,3 +350,16 @@ func ResetXact(x *BleXport) error {
 
        return reset(x, bl, r)
 }
+
+func DiscoverDeviceWithName(
+       bx *BleXport,
+       ownAddrType BleAddrType,
+       timeout time.Duration,
+       name string) (*BleDev, error) {
+
+       advPred := func(r BleAdvReport) bool {
+               return r.Name == name
+       }
+
+       return DiscoverDevice(bx, ownAddrType, timeout, advPred)
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/nmble/discover.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/discover.go b/nmxact/nmble/discover.go
new file mode 100644
index 0000000..7650044
--- /dev/null
+++ b/nmxact/nmble/discover.go
@@ -0,0 +1,142 @@
+package nmble
+
+import (
+       "fmt"
+       "time"
+
+       log "github.com/Sirupsen/logrus"
+
+       . "mynewt.apache.org/newtmgr/nmxact/bledefs"
+       "mynewt.apache.org/newtmgr/nmxact/nmxutil"
+)
+
+type DiscovererParams struct {
+       Bx          *BleXport
+       OwnAddrType BleAddrType
+       Passive     bool
+       Duration    time.Duration
+}
+
+// Listens for advertisements; reports the ones that match the specified
+// predicate.
+type Discoverer struct {
+       params    DiscovererParams
+       abortChan chan struct{}
+}
+
+func NewDiscoverer(params DiscovererParams) *Discoverer {
+       return &Discoverer{
+               params: params,
+       }
+}
+
+func (d *Discoverer) scanCancel() error {
+       r := NewBleScanCancelReq()
+
+       base := BleMsgBase{
+               Op:         -1,
+               Type:       -1,
+               Seq:        r.Seq,
+               ConnHandle: -1,
+       }
+
+       bl := NewBleListener()
+       if err := d.params.Bx.Bd.AddListener(base, bl); err != nil {
+               return err
+       }
+       defer d.params.Bx.Bd.RemoveListener(base)
+
+       if err := scanCancel(d.params.Bx, bl, r); err != nil {
+               return err
+       }
+
+       return nil
+}
+
+func (d *Discoverer) Start(advRptCb BleAdvRptFn) error {
+       // Scanning requires dedicated master privileges.
+       if err := d.params.Bx.AcquireMaster(d); err != nil {
+               return err
+       }
+       defer d.params.Bx.ReleaseMaster()
+
+       r := NewBleScanReq()
+       r.OwnAddrType = d.params.OwnAddrType
+       r.DurationMs = int(d.params.Duration / time.Millisecond)
+       r.FilterPolicy = BLE_SCAN_FILT_NO_WL
+       r.Limited = false
+       r.Passive = d.params.Passive
+       r.FilterDuplicates = true
+
+       base := BleMsgBase{
+               Op:         -1,
+               Type:       -1,
+               Seq:        r.Seq,
+               ConnHandle: -1,
+       }
+
+       bl := NewBleListener()
+       if err := d.params.Bx.Bd.AddListener(base, bl); err != nil {
+               return err
+       }
+       defer d.params.Bx.Bd.RemoveListener(base)
+
+       d.abortChan = make(chan struct{}, 1)
+       defer func() { d.abortChan = nil }()
+
+       err := actScan(d.params.Bx, bl, r, d.abortChan, advRptCb)
+       if !nmxutil.IsXport(err) {
+               // The transport did not restart; always attempt to cancel the 
scan
+               // operation.  In some cases, the host has already stopped 
scanning
+               // and will respond with an "ealready" error that can be 
ignored.
+               if err := d.scanCancel(); err != nil {
+                       log.Errorf("Failed to cancel scan in progress: %s",
+                               err.Error())
+               }
+       }
+
+       return err
+}
+
+func (d *Discoverer) Stop() error {
+       ch := d.abortChan
+
+       if ch == nil {
+               return fmt.Errorf("Attempt to stop inactive discoverer")
+       }
+
+       ch <- struct{}{}
+       return nil
+}
+
+// Discovers a single device.  After a device is successfully discovered,
+// discovery is stopped.
+func DiscoverDevice(
+       bx *BleXport,
+       ownAddrType BleAddrType,
+       duration time.Duration,
+       advPred BleAdvPredicate) (*BleDev, error) {
+
+       d := NewDiscoverer(DiscovererParams{
+               Bx:          bx,
+               OwnAddrType: ownAddrType,
+               Passive:     false,
+               Duration:    duration,
+       })
+
+       var dev *BleDev
+       advRptCb := func(adv BleAdvReport) {
+               if advPred(adv) {
+                       dev = &adv.Sender
+                       d.Stop()
+               }
+       }
+
+       if err := d.Start(advRptCb); err != nil {
+               if !nmxutil.IsScanTmo(err) {
+                       return nil, err
+               }
+       }
+
+       return dev, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/scan/scan.go
----------------------------------------------------------------------
diff --git a/nmxact/scan/scan.go b/nmxact/scan/scan.go
index cadf5f9..a7f67ec 100644
--- a/nmxact/scan/scan.go
+++ b/nmxact/scan/scan.go
@@ -6,15 +6,23 @@ import (
 )
 
 type ScanPeer struct {
-       HwId   []byte
-       Opaque interface{}
+       HwId     string
+       PeerSpec sesn.PeerSpec
 }
 
 type ScanFn func(peer ScanPeer)
 
+type CfgBle struct {
+       ScanPred bledefs.BleAdvPredicate
+}
+
 type Cfg struct {
+       // General configuration.
        ScanCb  ScanFn
        SesnCfg sesn.SesnCfg
+
+       // Transport-specific configuration.
+       Ble CfgBle
 }
 
 type Scanner interface {
@@ -28,23 +36,22 @@ 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
-               },
-       }
+       sc.Ble.EncryptWhen = bledefs.BLE_ENCRYPT_PRIV_ONLY
 
        cfg := Cfg{
                ScanCb:  ScanCb,
                SesnCfg: sc,
-       }
+               Ble: CfgBle{
+                       ScanPred: func(adv bledefs.BleAdvReport) bool {
+                               for _, u := range adv.Uuids16 {
+                                       if u == bledefs.OmpSvcUuid {
+                                               return true
+                                       }
+                               }
 
+                               return false
+                       },
+               },
+       }
        return cfg
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/99af734d/nmxact/sesn/sesn_cfg.go
----------------------------------------------------------------------
diff --git a/nmxact/sesn/sesn_cfg.go b/nmxact/sesn/sesn_cfg.go
index 0022640..042d8fd 100644
--- a/nmxact/sesn/sesn_cfg.go
+++ b/nmxact/sesn/sesn_cfg.go
@@ -13,55 +13,37 @@ const (
        MGMT_PROTO_OMP
 )
 
-type BleOnCloseFn func(s Sesn, peer bledefs.BleDev, err error)
+type OnCloseFn func(s Sesn, err error)
 
-// Specifies the BLE peer to connect to.
-type BlePeerSpec struct {
-       // This is filled in if you know the address of the peer to connect to.
-       Dev bledefs.BleDev
-
-       // Otherwise, we must scan for a peer to connect to.  This points to a
-       // function that indicates whether we should connect to the sender of 
the
-       // specified advertisement.  This function gets called each time an
-       // incoming advertisement is received.  If it returns true, the session
-       // will connect to the sender of the corresponding advertisement.  Set 
this
-       // to nil if you populate the Dev field.
-       ScanPred bledefs.BleAdvPredicate
-}
-
-func BlePeerSpecDev(dev bledefs.BleDev) BlePeerSpec {
-       return BlePeerSpec{Dev: dev}
-}
-
-func BlePeerSpecName(name string) BlePeerSpec {
-       return BlePeerSpec{
-               ScanPred: func(r bledefs.BleAdvReport) bool {
-                       return r.Name == name
-               },
-       }
+type PeerSpec struct {
+       Ble bledefs.BleDev
 }
 
 type SesnCfgBle struct {
        OwnAddrType  bledefs.BleAddrType
-       PeerSpec     BlePeerSpec
        ConnTries    int
        CloseTimeout time.Duration
-       OnCloseCb    BleOnCloseFn
 
-       Encrypt bledefs.BleEncryptWhen
+       EncryptWhen bledefs.BleEncryptWhen
 }
 
 type SesnCfg struct {
-       // Used with all transport types.
+       // General configuration.
        MgmtProto MgmtProto
+       PeerSpec  PeerSpec
+       OnCloseCb OnCloseFn
 
-       // Only used with BLE transports.
+       // Transport-specific configuration.
        Ble SesnCfgBle
 }
 
 func NewSesnCfg() SesnCfg {
        return SesnCfg{
+               // XXX: For now, assume an own address type of random static.  
In the
+               // future, there will need to be some global default, or 
something that
+               // gets read from blehostd.
                Ble: SesnCfgBle{
+                       OwnAddrType:  bledefs.BLE_ADDR_TYPE_RANDOM,
                        ConnTries:    3,
                        CloseTimeout: 30 * time.Second,
                },

Reply via email to