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 <ccoll...@apache.org> Authored: Mon May 1 14:21:54 2017 -0700 Committer: Christopher Collins <ccoll...@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 }