nmxact - Perform controller setup (addr,mtu) Prior to this change, nmxact assumed a random address was already configured and the preferred ATT MTU was already set. This assumption was valid because blehostd was hacked to do this upon host-controller sync.
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/06c80b76 Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/06c80b76 Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/06c80b76 Branch: refs/heads/master Commit: 06c80b760a69d3628d3bd98706bfad22b22a0f65 Parents: 9975ef7 Author: Christopher Collins <[email protected]> Authored: Wed Apr 5 15:16:44 2017 -0700 Committer: Christopher Collins <[email protected]> Committed: Wed Apr 5 16:04:26 2017 -0700 ---------------------------------------------------------------------- nmxact/nmble/ble_act.go | 110 +++++++++++++++++++++++++++++++++++++ nmxact/nmble/ble_proto.go | 121 +++++++++++++++++++++++++++++++---------- nmxact/nmble/ble_util.go | 24 ++++++++ nmxact/nmble/ble_xport.go | 114 ++++++++++++++++++++++++++++++++++++-- nmxact/nmble/dispatch.go | 54 ++++++++++-------- 5 files changed, 365 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06c80b76/nmxact/nmble/ble_act.go ---------------------------------------------------------------------- diff --git a/nmxact/nmble/ble_act.go b/nmxact/nmble/ble_act.go index cb6cb00..ff6dff9 100644 --- a/nmxact/nmble/ble_act.go +++ b/nmxact/nmble/ble_act.go @@ -3,6 +3,7 @@ package nmble import ( "encoding/json" + . "mynewt.apache.org/newtmgr/nmxact/bledefs" "mynewt.apache.org/newtmgr/nmxact/nmxutil" ) @@ -361,3 +362,112 @@ func scanCancel(x *BleXport, bl *BleListener, r *BleScanCancelReq) error { } } } + +// 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. +func genRandAddr(x *BleXport, bl *BleListener, r *BleGenRandAddrReq) ( + BleAddr, error) { + + j, err := json.Marshal(r) + if err != nil { + return BleAddr{}, err + } + + x.txNoSync(j) + for { + select { + case err := <-bl.ErrChan: + return BleAddr{}, err + + case bm := <-bl.BleChan: + switch msg := bm.(type) { + case *BleGenRandAddrRsp: + bl.Acked = true + if msg.Status != 0 { + return BleAddr{}, + StatusError(MSG_OP_RSP, MSG_TYPE_GEN_RAND_ADDR, + msg.Status) + } + return msg.Addr, nil + + default: + } + + case <-bl.AfterTimeout(x.RspTimeout()): + return BleAddr{}, BhdTimeoutError(MSG_TYPE_GEN_RAND_ADDR) + } + } +} + +// Configures the controller with the specified 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. +func setRandAddr(x *BleXport, bl *BleListener, r *BleSetRandAddrReq) error { + const msgType = MSG_TYPE_SET_RAND_ADDR + + j, err := json.Marshal(r) + if err != nil { + return err + } + + x.txNoSync(j) + for { + select { + case err := <-bl.ErrChan: + return err + + case bm := <-bl.BleChan: + switch msg := bm.(type) { + case *BleSetRandAddrRsp: + bl.Acked = true + if msg.Status != 0 { + return StatusError(MSG_OP_RSP, msgType, msg.Status) + } + return nil + + default: + } + + case <-bl.AfterTimeout(x.RspTimeout()): + return BhdTimeoutError(msgType) + } + } +} + +// Configures the host with the specified preferred ATT MTU. 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. +func setPreferredMtu(x *BleXport, bl *BleListener, + r *BleSetPreferredMtuReq) error { + + const msgType = MSG_TYPE_SET_PREFERRED_MTU + + j, err := json.Marshal(r) + if err != nil { + return err + } + + x.txNoSync(j) + for { + select { + case err := <-bl.ErrChan: + return err + + case bm := <-bl.BleChan: + switch msg := bm.(type) { + case *BleSetPreferredMtuRsp: + bl.Acked = true + if msg.Status != 0 { + return StatusError(MSG_OP_RSP, msgType, msg.Status) + } + return nil + + default: + } + + case <-bl.AfterTimeout(x.RspTimeout()): + return BhdTimeoutError(msgType) + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06c80b76/nmxact/nmble/ble_proto.go ---------------------------------------------------------------------- diff --git a/nmxact/nmble/ble_proto.go b/nmxact/nmble/ble_proto.go index 8545335..41afd51 100644 --- a/nmxact/nmble/ble_proto.go +++ b/nmxact/nmble/ble_proto.go @@ -216,22 +216,23 @@ const ( ) const ( - MSG_TYPE_ERR MsgType = 1 - MSG_TYPE_SYNC = 2 - MSG_TYPE_CONNECT = 3 - MSG_TYPE_TERMINATE = 4 - MSG_TYPE_DISC_ALL_SVCS = 5 - MSG_TYPE_DISC_SVC_UUID = 6 - MSG_TYPE_DISC_ALL_CHRS = 7 - MSG_TYPE_DISC_CHR_UUID = 8 - MSG_TYPE_WRITE = 9 - MSG_TYPE_WRITE_CMD = 10 - MSG_TYPE_EXCHANGE_MTU = 11 - MSG_TYPE_GEN_RAND_ADDR = 12 - MSG_TYPE_SET_RAND_ADDR = 13 - MSG_TYPE_CONN_CANCEL = 14 - MSG_TYPE_SCAN = 15 - MSG_TYPE_SCAN_CANCEL = 16 + MSG_TYPE_ERR MsgType = 1 + MSG_TYPE_SYNC = 2 + MSG_TYPE_CONNECT = 3 + MSG_TYPE_TERMINATE = 4 + MSG_TYPE_DISC_ALL_SVCS = 5 + MSG_TYPE_DISC_SVC_UUID = 6 + MSG_TYPE_DISC_ALL_CHRS = 7 + MSG_TYPE_DISC_CHR_UUID = 8 + MSG_TYPE_WRITE = 9 + MSG_TYPE_WRITE_CMD = 10 + MSG_TYPE_EXCHANGE_MTU = 11 + MSG_TYPE_GEN_RAND_ADDR = 12 + MSG_TYPE_SET_RAND_ADDR = 13 + MSG_TYPE_CONN_CANCEL = 14 + MSG_TYPE_SCAN = 15 + MSG_TYPE_SCAN_CANCEL = 16 + MSG_TYPE_SET_PREFERRED_MTU = 17 MSG_TYPE_SYNC_EVT = 2049 MSG_TYPE_CONNECT_EVT = 2050 @@ -251,18 +252,21 @@ var MsgOpStringMap = map[MsgOp]string{ } var MsgTypeStringMap = map[MsgType]string{ - MSG_TYPE_ERR: "error", - MSG_TYPE_SYNC: "sync", - MSG_TYPE_CONNECT: "connect", - MSG_TYPE_TERMINATE: "terminate", - MSG_TYPE_DISC_SVC_UUID: "disc_svc_uuid", - MSG_TYPE_DISC_CHR_UUID: "disc_chr_uuid", - MSG_TYPE_DISC_ALL_CHRS: "disc_all_chrs", - MSG_TYPE_WRITE_CMD: "write_cmd", - MSG_TYPE_EXCHANGE_MTU: "exchange_mtu", - MSG_TYPE_CONN_CANCEL: "conn_cancel", - MSG_TYPE_SCAN: "scan", - MSG_TYPE_SCAN_CANCEL: "scan_cancel", + MSG_TYPE_ERR: "error", + MSG_TYPE_SYNC: "sync", + MSG_TYPE_CONNECT: "connect", + MSG_TYPE_TERMINATE: "terminate", + MSG_TYPE_DISC_SVC_UUID: "disc_svc_uuid", + MSG_TYPE_DISC_CHR_UUID: "disc_chr_uuid", + MSG_TYPE_DISC_ALL_CHRS: "disc_all_chrs", + MSG_TYPE_WRITE_CMD: "write_cmd", + MSG_TYPE_EXCHANGE_MTU: "exchange_mtu", + MSG_TYPE_GEN_RAND_ADDR: "gen_rand_addr", + MSG_TYPE_SET_RAND_ADDR: "set_rand_addr", + MSG_TYPE_CONN_CANCEL: "conn_cancel", + MSG_TYPE_SCAN: "scan", + MSG_TYPE_SCAN_CANCEL: "scan_cancel", + MSG_TYPE_SET_PREFERRED_MTU: "set_preferred_mtu", MSG_TYPE_SYNC_EVT: "sync_evt", MSG_TYPE_CONNECT_EVT: "connect_evt", @@ -588,6 +592,47 @@ type BleMtuChangeEvt struct { Mtu int `json:"mtu"` } +type BleGenRandAddrReq struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Nrpa bool `json:"nrpa"` +} + +type BleGenRandAddrRsp struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Status int `json:"status"` + Addr BleAddr `json:"addr"` +} + +type BleSetRandAddrReq struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Addr BleAddr `json:"addr"` +} + +type BleSetRandAddrRsp struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Status int `json:"status"` +} + type BleScanReq struct { // Header Op MsgOp `json:"op"` @@ -651,6 +696,26 @@ type BleScanCancelRsp struct { Status int `json:"status"` } +type BleSetPreferredMtuReq struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Mtu uint16 `json:"mtu"` +} + +type BleSetPreferredMtuRsp struct { + // Header + Op MsgOp `json:"op"` + Type MsgType `json:"type"` + Seq BleSeq `json:"seq"` + + // Mandatory + Status int `json:"status"` +} + func ErrCodeToString(e int) string { var s string http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06c80b76/nmxact/nmble/ble_util.go ---------------------------------------------------------------------- diff --git a/nmxact/nmble/ble_util.go b/nmxact/nmble/ble_util.go index 07cd8c3..a61618f 100644 --- a/nmxact/nmble/ble_util.go +++ b/nmxact/nmble/ble_util.go @@ -145,6 +145,22 @@ func NewBleExchangeMtuReq() *BleExchangeMtuReq { } } +func NewBleGenRandAddrReq() *BleGenRandAddrReq { + return &BleGenRandAddrReq{ + Op: MSG_OP_REQ, + Type: MSG_TYPE_GEN_RAND_ADDR, + Seq: NextSeq(), + } +} + +func NewBleSetRandAddrReq() *BleSetRandAddrReq { + return &BleSetRandAddrReq{ + Op: MSG_OP_REQ, + Type: MSG_TYPE_SET_RAND_ADDR, + Seq: NextSeq(), + } +} + func NewBleWriteCmdReq() *BleWriteCmdReq { return &BleWriteCmdReq{ Op: MSG_OP_REQ, @@ -172,3 +188,11 @@ func NewBleScanCancelReq() *BleScanCancelReq { Seq: NextSeq(), } } + +func NewBleSetPreferredMtuReq() *BleSetPreferredMtuReq { + return &BleSetPreferredMtuReq{ + Op: MSG_OP_REQ, + Type: MSG_TYPE_SET_PREFERRED_MTU, + Seq: NextSeq(), + } +} http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06c80b76/nmxact/nmble/ble_xport.go ---------------------------------------------------------------------- diff --git a/nmxact/nmble/ble_xport.go b/nmxact/nmble/ble_xport.go index f957341..4f44577 100644 --- a/nmxact/nmble/ble_xport.go +++ b/nmxact/nmble/ble_xport.go @@ -10,32 +10,54 @@ import ( log "github.com/Sirupsen/logrus" "mynewt.apache.org/newt/util/unixchild" + . "mynewt.apache.org/newtmgr/nmxact/bledefs" "mynewt.apache.org/newtmgr/nmxact/nmxutil" "mynewt.apache.org/newtmgr/nmxact/sesn" ) type XportCfg struct { + // *********************** + // *** Required fields *** + // *********************** + // Path of Unix domain socket to create and listen on. SockPath string // Path of the blehostd executable. BlehostdPath string + // Path of the BLE controller device (e.g., /dev/ttyUSB0). + DevPath string + + // *********************** + // *** Optional fields *** + // *********************** + // How long to wait for the blehostd process to connect to the Unix domain // socket. + // Default: 1 second. BlehostdAcceptTimeout time.Duration - // Whether to restart the blehostd process if it terminates. - BlehostdRestart bool - // How long to wait for a JSON response from the blehostd process. + // Default: 1 second. BlehostdRspTimeout time.Duration - // Path of the BLE controller device (e.g., /dev/ttyUSB0). - DevPath string + // Whether to restart the blehostd process if it terminates. + // Default: true. + BlehostdRestart bool // How long to allow for the host and controller to sync at startup. + // Default: 10 seconds. SyncTimeout time.Duration + + // The static random address to use. Set to nil if one should be + // generated. + // Default: nil (auto-generate). + RandAddr *BleAddr + + // The value to specify during ATT MTU exchange. + // Default: 512. + PreferredMtu uint16 } func NewXportCfg() XportCfg { @@ -44,6 +66,7 @@ func NewXportCfg() XportCfg { BlehostdRspTimeout: time.Second, BlehostdRestart: true, SyncTimeout: 10 * time.Second, + PreferredMtu: 512, } } @@ -51,10 +74,10 @@ type BleXportState int const ( BLE_XPORT_STATE_DORMANT BleXportState = iota + BLE_XPORT_STATE_STOPPING BLE_XPORT_STATE_STOPPED BLE_XPORT_STATE_STARTING BLE_XPORT_STATE_STARTED - BLE_XPORT_STATE_STOPPING ) // Implements xport.Xport. @@ -67,6 +90,7 @@ type BleXport struct { shutdownChan chan bool readyChan chan error numReadyListeners int + randAddr *BleAddr mtx sync.Mutex cfg XportCfg @@ -96,6 +120,64 @@ func (bx *BleXport) createUnixChild() { bx.client = unixchild.New(config) } +func (bx *BleXport) genRandAddr() (BleAddr, error) { + r := NewBleGenRandAddrReq() + base := BleMsgBase{ + Op: -1, + Type: -1, + Seq: r.Seq, + ConnHandle: -1, + } + + bl := NewBleListener() + if err := bx.Bd.AddListener(base, bl); err != nil { + return BleAddr{}, err + } + defer bx.Bd.RemoveListener(base) + + return genRandAddr(bx, bl, r) +} + +func (bx *BleXport) setRandAddr(addr BleAddr) error { + r := NewBleSetRandAddrReq() + r.Addr = addr + + base := BleMsgBase{ + Op: -1, + Type: -1, + Seq: r.Seq, + ConnHandle: -1, + } + + bl := NewBleListener() + if err := bx.Bd.AddListener(base, bl); err != nil { + return err + } + defer bx.Bd.RemoveListener(base) + + return setRandAddr(bx, bl, r) +} + +func (bx *BleXport) setPreferredMtu(mtu uint16) error { + r := NewBleSetPreferredMtuReq() + r.Mtu = mtu + + base := BleMsgBase{ + Op: -1, + Type: -1, + Seq: r.Seq, + ConnHandle: -1, + } + + bl := NewBleListener() + if err := bx.Bd.AddListener(base, bl); err != nil { + return err + } + defer bx.Bd.RemoveListener(base) + + return setPreferredMtu(bx, bl, r) +} + func (bx *BleXport) BuildSesn(cfg sesn.SesnCfg) (sesn.Sesn, error) { switch cfg.MgmtProto { case sesn.MGMT_PROTO_NMP: @@ -386,6 +468,26 @@ func (bx *BleXport) startOnce() error { } }() + if bx.randAddr == nil { + addr, err := bx.genRandAddr() + if err != nil { + bx.shutdown(true, err) + return err + } + + bx.randAddr = &addr + } + + if err := bx.setRandAddr(*bx.randAddr); err != nil { + bx.shutdown(true, err) + return err + } + + if err := bx.setPreferredMtu(bx.cfg.PreferredMtu); err != nil { + bx.shutdown(true, err) + return err + } + if !bx.setStateFrom(BLE_XPORT_STATE_STARTING, BLE_XPORT_STATE_STARTED) { bx.shutdown(true, err) return nmxutil.NewXportError( http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06c80b76/nmxact/nmble/dispatch.go ---------------------------------------------------------------------- diff --git a/nmxact/nmble/dispatch.go b/nmxact/nmble/dispatch.go index 583f3a4..06d2847 100644 --- a/nmxact/nmble/dispatch.go +++ b/nmxact/nmble/dispatch.go @@ -84,18 +84,21 @@ 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 connCancelRspCtor() BleMsg { return &BleConnCancelRsp{} } -func scanRspCtor() BleMsg { return &BleScanRsp{} } -func scanCancelRspCtor() BleMsg { return &BleScanCancelRsp{} } +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 syncEvtCtor() BleMsg { return &BleSyncEvt{} } func connectEvtCtor() BleMsg { return &BleConnectEvt{} } @@ -107,18 +110,21 @@ func mtuChangeEvtCtor() BleMsg { return &BleMtuChangeEvt{} } func scanEvtCtor() BleMsg { return &BleScanEvt{} } var msgCtorMap = map[OpTypePair]msgCtor{ - {MSG_OP_RSP, MSG_TYPE_ERR}: errRspCtor, - {MSG_OP_RSP, MSG_TYPE_SYNC}: syncRspCtor, - {MSG_OP_RSP, MSG_TYPE_CONNECT}: connectRspCtor, - {MSG_OP_RSP, MSG_TYPE_TERMINATE}: terminateRspCtor, - {MSG_OP_RSP, MSG_TYPE_DISC_SVC_UUID}: discSvcUuidRspCtor, - {MSG_OP_RSP, MSG_TYPE_DISC_CHR_UUID}: discChrUuidRspCtor, - {MSG_OP_RSP, MSG_TYPE_DISC_ALL_CHRS}: discAllChrsRspCtor, - {MSG_OP_RSP, MSG_TYPE_WRITE_CMD}: writeCmdRspCtor, - {MSG_OP_RSP, MSG_TYPE_EXCHANGE_MTU}: exchangeMtuRspCtor, - {MSG_OP_RSP, MSG_TYPE_CONN_CANCEL}: connCancelRspCtor, - {MSG_OP_RSP, MSG_TYPE_SCAN}: scanRspCtor, - {MSG_OP_RSP, MSG_TYPE_SCAN_CANCEL}: scanCancelRspCtor, + {MSG_OP_RSP, MSG_TYPE_ERR}: errRspCtor, + {MSG_OP_RSP, MSG_TYPE_SYNC}: syncRspCtor, + {MSG_OP_RSP, MSG_TYPE_CONNECT}: connectRspCtor, + {MSG_OP_RSP, MSG_TYPE_TERMINATE}: terminateRspCtor, + {MSG_OP_RSP, MSG_TYPE_DISC_SVC_UUID}: discSvcUuidRspCtor, + {MSG_OP_RSP, MSG_TYPE_DISC_CHR_UUID}: discChrUuidRspCtor, + {MSG_OP_RSP, MSG_TYPE_DISC_ALL_CHRS}: discAllChrsRspCtor, + {MSG_OP_RSP, MSG_TYPE_WRITE_CMD}: writeCmdRspCtor, + {MSG_OP_RSP, MSG_TYPE_EXCHANGE_MTU}: exchangeMtuRspCtor, + {MSG_OP_RSP, MSG_TYPE_GEN_RAND_ADDR}: genRandAddrRspCtor, + {MSG_OP_RSP, MSG_TYPE_SET_RAND_ADDR}: setRandAddrRspCtor, + {MSG_OP_RSP, MSG_TYPE_CONN_CANCEL}: connCancelRspCtor, + {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_EVT, MSG_TYPE_SYNC_EVT}: syncEvtCtor, {MSG_OP_EVT, MSG_TYPE_CONNECT_EVT}: connectEvtCtor,
