You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2015/11/14 02:26:33 UTC
incubator-mynewt-larva git commit: Start of connection process
finished. Sending connect requests and receiving them and starting the
connection is finished.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master c6ccb0e8e -> d478f7bce
Start of connection process finished. Sending connect requests and receiving them and starting the connection is finished.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/commit/d478f7bc
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/d478f7bc
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/d478f7bc
Branch: refs/heads/master
Commit: d478f7bce60928125771d781b051dab566b42ad8
Parents: c6ccb0e
Author: wes3 <wi...@micosa.io>
Authored: Fri Nov 13 17:26:13 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Fri Nov 13 17:26:28 2015 -0800
----------------------------------------------------------------------
.../controller/include/controller/ble_ll.h | 13 +-
.../controller/include/controller/ble_ll_adv.h | 3 +
.../controller/include/controller/ble_ll_conn.h | 16 +
.../controller/include/controller/ble_ll_scan.h | 45 +-
net/nimble/controller/src/ble_ll.c | 53 +-
net/nimble/controller/src/ble_ll_adv.c | 175 ++++--
net/nimble/controller/src/ble_ll_conn.c | 604 +++++++++++++++++--
net/nimble/controller/src/ble_ll_hci.c | 1 +
net/nimble/controller/src/ble_ll_scan.c | 81 ++-
net/nimble/drivers/nrf52/src/ble_phy.c | 5 +
10 files changed, 829 insertions(+), 167 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index c93b55f..317cb2c 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -70,8 +70,8 @@ extern struct ble_ll_obj g_ble_ll_data;
#define BLE_LL_STATE_STANDBY (0)
#define BLE_LL_STATE_ADV (1)
#define BLE_LL_STATE_SCANNING (2)
-#define BLE_LL_STATE_INITITATING (3)
-#define BLE_LL_STATE_CONNECT (4)
+#define BLE_LL_STATE_INITIATING (3)
+#define BLE_LL_STATE_CONNECTION (4)
/* BLE LL Task Events */
#define BLE_LL_EVENT_HCI_CMD (OS_EVENT_T_PERUSER)
@@ -402,15 +402,6 @@ struct ble_conn_req_data
#define BLE_CONN_REQ_HOP_MASK (0x1F)
#define BLE_CONN_REQ_SCA_MASK (0xE0)
-#define BLE_MASTER_SCA_251_500_PPM (0)
-#define BLE_MASTER_SCA_151_250_PPM (1)
-#define BLE_MASTER_SCA_101_150_PPM (2)
-#define BLE_MASTER_SCA_76_100_PPM (3)
-#define BLE_MASTER_SCA_51_75_PPM (4)
-#define BLE_MASTER_SCA_31_50_PPM (5)
-#define BLE_MASTER_SCA_21_30_PPM (6)
-#define BLE_MASTER_SCA_0_20_PPM (7)
-
/*
* Initiator filter policy
*
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/include/controller/ble_ll_adv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_adv.h b/net/nimble/controller/include/controller/ble_ll_adv.h
index 664668a..1e985b0 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -125,4 +125,7 @@ int ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu);
/* Boolean function denoting whether or not the whitelist can be changed */
int ble_ll_adv_can_chg_whitelist(void);
+/* Called when a connection request has been received at the link layer */
+void ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, uint8_t flags);
+
#endif /* H_BLE_LL_ADV_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index 7c58b67..ff62ff6 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -17,7 +17,23 @@
#ifndef H_BLE_LL_CONN_
#define H_BLE_LL_CONN_
+/* Definitions for source clock accuracy */
+#define BLE_MASTER_SCA_251_500_PPM (0)
+#define BLE_MASTER_SCA_151_250_PPM (1)
+#define BLE_MASTER_SCA_101_150_PPM (2)
+#define BLE_MASTER_SCA_76_100_PPM (3)
+#define BLE_MASTER_SCA_51_75_PPM (4)
+#define BLE_MASTER_SCA_31_50_PPM (5)
+#define BLE_MASTER_SCA_21_30_PPM (6)
+#define BLE_MASTER_SCA_0_20_PPM (7)
+
int ble_ll_conn_create(uint8_t *cmdbuf);
int ble_ll_conn_create_cancel(void);
+int ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva);
+int ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva);
+void ble_ll_init_rx_pdu_proc(uint8_t pdu_type, uint8_t *rxbuf, uint8_t crcok);
+int ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu);
+int ble_ll_init_rx_pdu_start(uint8_t pdu_type);
+void ble_ll_conn_slave_start(uint8_t *rxbuf);
#endif /* H_BLE_LL_CONN_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/include/controller/ble_ll_scan.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_scan.h b/net/nimble/controller/include/controller/ble_ll_scan.h
index b7ce24f..bb296e7 100644
--- a/net/nimble/controller/include/controller/ble_ll_scan.h
+++ b/net/nimble/controller/include/controller/ble_ll_scan.h
@@ -17,6 +17,10 @@
#ifndef H_BLE_LL_SCAN_
#define H_BLE_LL_SCAN_
+/*
+ * Configuration items for the number of duplicate advertisers and the
+ * number of advertisers from which we have heard a scan response
+ */
#define BLE_LL_SCAN_CFG_NUM_DUP_ADVS (8)
#define BLE_LL_SCAN_CFG_NUM_SCAN_RSP_ADVS (8)
@@ -28,9 +32,6 @@
#error "Cannot have more than 255 scan response entries!"
#endif
-/* Maximum amount of scan response data in a scan response */
-#define BLE_SCAN_RSP_DATA_MAX_LEN (31)
-
/*
* SCAN_REQ
* -> ScanA (6 bytes)
@@ -56,9 +57,36 @@
* Sent by the LL in the advertising state; received by the LL in the
* scanning state.
*/
+#define BLE_SCAN_RSP_DATA_MAX_LEN (31)
#define BLE_SCAN_RSP_MIN_LEN (6)
#define BLE_SCAN_RSP_MAX_LEN (6 + BLE_SCAN_RSP_DATA_MAX_LEN)
+/* Scanning state machine (used when initiating as well) */
+struct ble_ll_scan_sm
+{
+ uint8_t scan_enabled;
+ uint8_t scan_type;
+ uint8_t own_addr_type;
+ uint8_t scan_chan;
+ uint8_t scan_filt_policy;
+ uint8_t scan_filt_dups;
+ uint8_t scan_rsp_pending;
+ uint8_t scan_rsp_cons_fails;
+ uint8_t scan_rsp_cons_ok;
+ uint16_t upper_limit;
+ uint16_t backoff_count;
+ uint16_t scan_itvl;
+ uint16_t scan_window;
+ uint32_t scan_win_start_time;
+ struct os_mbuf *scan_req_pdu;
+ struct os_event scan_win_end_ev;
+};
+
+/* Scan types */
+#define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE)
+#define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE)
+#define BLE_SCAN_TYPE_INITIATE (2)
+
/*---- HCI ----*/
/* Set scanning parameters */
int ble_ll_scan_set_scan_params(uint8_t *cmd);
@@ -89,11 +117,20 @@ int ble_ll_scan_can_chg_whitelist(void);
/* Boolean function returning true if scanning enabled */
int ble_ll_scan_enabled(void);
+/* Boolean function returns true if whitelist is enabled for scanning */
+int ble_ll_scan_whitelist_enabled(void);
+
/* Initialize the scanner when we start initiating */
struct hci_create_conn;
-void ble_ll_scan_initiator_start(struct hci_create_conn *hcc);
+int ble_ll_scan_initiator_start(struct hci_create_conn *hcc);
/* Returns the PDU allocated by the scanner */
struct os_mbuf *ble_ll_scan_get_pdu(void);
+/* Stop the scanning state machine */
+void ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm);
+
+/* Returns the global scanning state machine */
+struct ble_ll_scan_sm *ble_ll_scan_sm_get(void);
+
#endif /* H_BLE_LL_SCAN_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index be327c3..645fdde 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -24,8 +24,17 @@
#include "controller/ble_ll_adv.h"
#include "controller/ble_ll_sched.h"
#include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_conn.h"
#include "controller/ble_ll_hci.h"
+/*
+ * XXX: Just thought of something! Can I always set the DEVMATCH bit at
+ * the lower layer? This way the LL just looks at devmatch when it wants
+ * to see if a packet is "for us". I am referring to packets that pass
+ * whitelisting but also need to be "for us" (connect requests, scan requests,
+ * scan responses, etc). Look into this. This way I would not need to do
+ additional whitelist checks at the upper layer. */
+
/* XXX:
*
* 1) use the sanity task!
@@ -202,21 +211,29 @@ ble_ll_set_random_addr(uint8_t *addr)
return rc;
}
+/**
+ * Checks to see if an address is our device address (either public or
+ * random)
+ *
+ * @param addr
+ * @param addr_type
+ *
+ * @return int
+ */
int
ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
{
int rc;
uint8_t *our_addr;
- rc = 0;
if (addr_type) {
- our_addr = g_dev_addr;
- } else {
our_addr = g_random_addr;
+ } else {
+ our_addr = g_dev_addr;
}
rc = 0;
- if (!memcmp(our_addr, g_random_addr, BLE_DEV_ADDR_LEN)) {
+ if (!memcmp(our_addr, addr, BLE_DEV_ADDR_LEN)) {
rc = 1;
}
@@ -245,9 +262,9 @@ ble_ll_pdu_tx_time_get(uint16_t len)
/**
* ll rx pkt in proc
*
- * Process received packet from PHY
+ * Process received packet from PHY.
*
- * Callers: LL task.
+ * Context: Link layer task
*
*/
void
@@ -295,7 +312,9 @@ ble_ll_rx_pkt_in_proc(void)
/* Process the PDU */
switch (g_ble_ll_data.ll_state) {
case BLE_LL_STATE_ADV:
- /* XXX: implement this */
+ if (ble_hdr->crcok && (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+ ble_ll_adv_conn_req_rxd(rxbuf, ble_hdr->flags);
+ }
break;
case BLE_LL_STATE_SCANNING:
if (ble_hdr->crcok) {
@@ -310,8 +329,14 @@ ble_ll_rx_pkt_in_proc(void)
ble_phy_rx();
}
break;
- default:
+ case BLE_LL_STATE_INITIATING:
+ ble_ll_init_rx_pdu_proc(pdu_type, rxbuf, ble_hdr->crcok);
+ break;
+ case BLE_LL_STATE_CONNECTION:
/* XXX: implement */
+ break;
+ default:
+ /* We should not receive packets in standby state! */
assert(0);
break;
}
@@ -369,9 +394,13 @@ ble_ll_rx_start(struct os_mbuf *rxpdu)
rc = -1;
}
break;
+ case BLE_LL_STATE_INITIATING:
+ rc = ble_ll_init_rx_pdu_start(pdu_type);
+ break;
case BLE_LL_STATE_SCANNING:
rc = ble_ll_scan_rx_pdu_start(pdu_type, rxpdu);
break;
+ case BLE_LL_STATE_CONNECTION:
default:
/* XXX: should we really assert here? What to do... */
rc = -1;
@@ -465,6 +494,14 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t crcok)
rc = ble_ll_scan_rx_pdu_end(rxpdu);
}
break;
+ case BLE_LL_STATE_INITIATING:
+ if (crcok) {
+ rc = ble_ll_init_rx_pdu_end(rxpdu);
+ }
+ break;
+ case BLE_LL_STATE_CONNECTION:
+ /* XXX */
+ break;
default:
assert(0);
break;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index 18af12d..67acf8f 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -25,6 +25,7 @@
#include "controller/ble_ll_adv.h"
#include "controller/ble_ll_sched.h"
#include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_conn.h"
#include "controller/ble_ll_whitelist.h"
#include "hal/hal_cputime.h"
#include "hal/hal_gpio.h"
@@ -52,12 +53,18 @@
* now, we set it to max.
* 6) Currently, when we set scheduling events, we dont take into account
* processor overhead/delays. We will want to do that.
- * 7) Need to implement the whole HCI command done stuff.
* 8) For set adv enable command: if we get a connection, or we time out,
* we need to send a CONNECTION COMPLETE event. Do this.
* 9) How does the advertising channel tx power get set? I dont implement
* that currently.
* 10) Deal with whitelisting at LL when pdu is handed up to LL task.
+ * 11) What about High duty cycle advertising? Do we exit the advertising state
+ * after 1.28 seconds automatically? Seems like we do!!! 4.4.2.4.2 Vol 6 Part B
+ * => YES! we have to implement this and set back a CONN COMPLETE event with
+ * error code DIRECTED ADV TIMEOUT.
+ * 12) Something to consider: if we are attempting to advertise but dont have
+ * any connection state machines available, I dont think we should enable
+ * advertising.
*/
/*
@@ -147,6 +154,37 @@ ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm)
return adv_chan;
}
+
+/**
+ * Compares the advertiser address in an advertising PDU with our
+ * address to see if there is a match
+ *
+ * @param rxbuf Pointer to received PDU
+ *
+ * @return int Returns memcmp return values (0 = match).
+ */
+static int
+ble_ll_adv_addr_cmp(uint8_t *rxbuf)
+{
+ int rc;
+ uint8_t *adva;
+ uint8_t *our_addr;
+ uint8_t rxaddr_type;
+
+ /* Determine if this is addressed to us */
+ rxaddr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
+ if (rxaddr_type) {
+ our_addr = g_random_addr;
+ } else {
+ our_addr = g_dev_addr;
+ }
+
+ adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
+ rc = memcmp(our_addr, adva, BLE_DEV_ADDR_LEN);
+
+ return rc;
+}
+
/**
* Create the advertising PDU
*
@@ -753,61 +791,60 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t len)
}
/**
- * Called when the LL receives a scan request.
+ * Called when the LL receives a scan request or connection request
*
* Context: Called from interrupt context.
*
* @param rxbuf
*
- * @return -1: scan request not for us.
- * 0: Scan request is for us and we successfully went from rx to tx.
+ * @return -1: request not for us or is a connect request.
+ * 0: request (scan) is for us and we successfully went from rx to tx.
* > 0: PHY error attempting to go from rx to tx.
*/
static int
-ble_ll_adv_rx_scan_req(struct os_mbuf *rxpdu)
+ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
{
int rc;
- uint8_t rxaddr_type;
- uint8_t *our_addr;
- uint8_t *adva;
- uint8_t addr_type;
+ uint8_t chk_whitelist;
+ uint8_t txadd;
uint8_t *rxbuf;
struct ble_mbuf_hdr *ble_hdr;
struct ble_ll_adv_sm *advsm;
- /* Determine if this is addressed to us */
rxbuf = rxpdu->om_data;
- rxaddr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
- if (rxaddr_type) {
- our_addr = g_random_addr;
+ if (ble_ll_adv_addr_cmp(rxbuf)) {
+ return -1;
+ }
+
+ /* Set device match bit if we are whitelisting */
+ advsm = &g_ble_ll_adv_sm;
+ if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
+ chk_whitelist = advsm->adv_filter_policy & 1;
} else {
- our_addr = g_dev_addr;
+ chk_whitelist = advsm->adv_filter_policy & 2;
}
- rc = -1;
- adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
- if (!memcmp(our_addr, adva, BLE_DEV_ADDR_LEN)) {
- /* Set device match bit if we are whitelisting */
- advsm = &g_ble_ll_adv_sm;
- if (advsm->adv_filter_policy & 1) {
- /* Get the scanners address type */
- if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
- addr_type = BLE_ADDR_TYPE_RANDOM;
- } else {
- addr_type = BLE_ADDR_TYPE_PUBLIC;
- }
-
- /* Check for whitelist match */
- if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN,
- addr_type)) {
- return rc;
- } else {
- ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
- ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
- }
+ /* Set device match bit if we are whitelisting */
+ if (chk_whitelist) {
+ /* Get the scanners address type */
+ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+ txadd = BLE_ADDR_TYPE_RANDOM;
+ } else {
+ txadd = BLE_ADDR_TYPE_PUBLIC;
}
- /* Setup to transmit the scan response */
+ /* Check for whitelist match */
+ if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, txadd)) {
+ return -1;
+ } else {
+ ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+ ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
+ }
+ }
+
+ /* Setup to transmit the scan response if appropriate */
+ rc = -1;
+ if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_RX_TX,
BLE_PHY_TRANSITION_NONE);
if (!rc) {
@@ -819,16 +856,60 @@ ble_ll_adv_rx_scan_req(struct os_mbuf *rxpdu)
}
/**
- * Called on phy rx pdu end when in advertising state.
+ * Called when a connect request has been received.
+ *
+ * Context: Link Layer
+ *
+ * @param rxbuf
+ * @param flags
+ */
+void
+ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, uint8_t flags)
+{
+ int valid;
+ struct ble_ll_adv_sm *advsm;
+
+ /* Check filter policy. */
+ valid = 0;
+ advsm = &g_ble_ll_adv_sm;
+ if (advsm->adv_filter_policy & 2) {
+ if (flags & BLE_MBUF_HDR_F_DEVMATCH) {
+ /* valid connection request received */
+ valid = 1;
+ }
+ } else {
+ /* If this is for us? */
+ if (!ble_ll_adv_addr_cmp(rxbuf)) {
+ valid = 1;
+ }
+ }
+
+ if (valid) {
+ /* Stop advertising and start connection */
+ ble_ll_adv_sm_stop(advsm);
+ ble_ll_conn_slave_start(rxbuf);
+ }
+}
+
+/**
+ * Called on phy rx pdu end when in advertising state.
+ *
+ * There are only two pdu types we care about in this state: scan requests
+ * and connection requests. When we receive a scan request we must determine if
+ * we need to send a scan response and that needs to be acted on within T_IFS.
+ *
+ * When we receive a connection request, we need to determine if we will allow
+ * this device to start a connection with us. However, no immediate response is
+ * sent so we handle this at the link layer task.
*
* Context: Interrupt
*
- * @param pdu_type
- * @param rxpdu
+ * @param pdu_type Type of pdu received.
+ * @param rxpdu Pointer to received PDU
*
* @return int
* < 0: Disable the phy after reception.
- * == 0: Do not disable the PHY as we are gi
+ * == 0: Do not disable the PHY
* > 0: Do not disable PHY as that has already been done.
*/
int
@@ -836,22 +917,20 @@ ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu)
{
int rc;
- /* We only care about scan requests and connection requests */
rc = -1;
- if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
- rc = ble_ll_adv_rx_scan_req(rxpdu);
+ if ((pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) ||
+ (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+ /* Process request */
+ rc = ble_ll_adv_rx_req(pdu_type, rxpdu);
if (rc) {
/* XXX: One thing left to reconcile here. We have
* the advertisement schedule element still running.
* How to deal with the end of the advertising event?
* Need to figure that out.
+ *
+ * XXX: This applies to connection requests as well.
*/
}
- } else {
- if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ) {
- rc = 0;
- /* XXX: deal with this. Dont forget filter policy */
- }
}
return rc;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 0f1f46c..58b2097 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -22,25 +22,53 @@
#include "nimble/ble.h"
#include "nimble/hci_common.h"
#include "controller/ble_ll.h"
+#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_conn.h"
#include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_whitelist.h"
#include "controller/ble_phy.h"
/* XXX TODO
* 1) Implemement connection supervisor timeout.
- * 2) Create connection request.
- * 3) Process rxd connection request.
- * 4) What about channel map. Where is that set?
- * 5) Review data channel index selection
- * 6) Closing the connection: the MD bit.
- * 7) notifying host about connections: how often do we need to do this? On
+ * 2) Add set channel map command and implement channel change procedure.
+ * 3) Closing the connection: the MD bit.
+ * 4) notifying host about connections: how often do we need to do this? On
* creation, establishment and/or loss?
- * 8) Deal with window widening. Easy...
- * 9) Close connection if window widening gets too big! 4.5.7
- * 10) portions of the connect request need to be modified (possibly) based
- * on the advertiser.
+ * 5) Deal with window widening. Easy...
+ * 6) Close connection if window widening gets too big! 4.5.7
+ * 7) How does state get set to ESTABLISHED? Do that...
+ * 8) In both cases when I start the connection SM I need to set up a
+ * schedule item to deal with receiving packets and transmitting them.
+ * 9) Implement flow control and all that.
+ * 10) Implement getting a data packet. How do we do that?
+ * 11) Send connection complete event when connection dies.
*/
+/* XXX: Something I need to think about. At what point do I consider the
+ * connection created? When I send the connect request or when I send
+ * the connection complete event. I just dont want there to be weird race
+ * conditions if I get cancel connection create command. I want to make
+ * sure that I deal with that properly. I think the connection state will tell
+ * me. Anyway, just make sure there are no issues here
+ */
+
+/* Channel map size */
+#define BLE_LL_CONN_CHMAP_LEN (5)
+
+/* Configuration parameters */
+#define BLE_LL_CONN_CFG_TX_WIN_SIZE (1)
+#define BLE_LL_CONN_CFG_TX_WIN_OFF (0)
+#define BLE_LL_CONN_CFG_MASTER_SCA (BLE_MASTER_SCA_251_500_PPM << 5)
+#define BLE_LL_CONN_CFG_MAX_CONNS (8)
+
+/* Roles */
+#define BLE_LL_CONN_ROLE_NONE (0)
+#define BLE_LL_CONN_ROLE_MASTER (1)
+#define BLE_LL_CONN_ROLE_SLAVE (2)
+
+/* Connection request */
+#define BLE_LL_CONN_REQ_ADVA_OFF (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
+
/* Scanning state machine */
struct ble_ll_conn_sm
{
@@ -48,17 +76,23 @@ struct ble_ll_conn_sm
uint8_t unmapped_chan;
uint8_t last_unmapped_chan;
uint8_t num_used_chans;
- uint8_t chanmap[5];
+ uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
uint8_t hop_inc;
uint8_t conn_state;
+ uint8_t conn_role;
+ uint8_t master_sca;
+ uint8_t conn_tx_win_size;
uint8_t own_addr_type;
uint8_t peer_addr_type;
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
uint16_t conn_spvn_tmo;
+ uint16_t conn_itvl;
uint16_t conn_slave_latency;
uint16_t conn_event_cntr;
+ uint16_t conn_handle;
+ uint16_t conn_tx_win_off;
uint32_t access_addr;
- struct os_mbuf *conn_req_pdu;
+ uint32_t crcinit; /* only low 24 bits used */
};
struct ble_ll_conn_sm g_ble_ll_conn_sm;
@@ -68,6 +102,84 @@ struct ble_ll_conn_sm g_ble_ll_conn_sm;
#define BLE_LL_CONN_STATE_CREATED (1)
#define BLE_LL_CONN_STATE_ESTABLISHED (2)
+/* Connection handles */
+static uint8_t g_ble_ll_conn_handles[(BLE_LL_CONN_CFG_MAX_CONNS + 7) / 8];
+static uint16_t g_ble_ll_conn_handles_out;
+
+struct os_mempool g_ble_ll_conn_pool;
+os_membuf_t g_ble_ll_conn_buf[OS_MEMPOOL_SIZE(BLE_LL_CONN_CFG_MAX_CONNS,
+ sizeof(struct ble_ll_conn_sm))];
+
+/**
+ * Calculates the number of used channels in the channel map
+ *
+ * @param chmap
+ *
+ * @return uint8_t Number of used channels
+ */
+uint8_t
+ble_ll_conn_calc_used_chans(uint8_t *chmap)
+{
+ int i;
+ int j;
+ uint8_t mask;
+ uint8_t chanbyte;
+ uint8_t used_channels;
+
+ used_channels = 0;
+ for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; ++i) {
+ chanbyte = chmap[i];
+ if (chanbyte) {
+ if (chanbyte == 0xff) {
+ used_channels += 8;
+ } else {
+ mask = 0x01;
+ for (j = 0; j < 8; ++j) {
+ if (chanbyte & mask) {
+ ++used_channels;
+ }
+ mask <<= 1;
+ }
+ }
+ }
+ }
+ return used_channels;
+}
+
+
+static uint16_t
+ble_ll_conn_get_unused_handle(void)
+{
+ uint8_t bytepos;
+ uint8_t bitpos;
+ int handle;
+
+ /* Keep track of total number so you can deny it! */
+ if (g_ble_ll_conn_handles_out == BLE_LL_CONN_CFG_MAX_CONNS) {
+ /* Handles can only be in range 0 to 0x0EFF */
+ return 0xFFFF;
+ }
+
+ /* Return an unused handle */
+ for (handle = 0; handle < BLE_LL_CONN_CFG_MAX_CONNS; ++handle) {
+ /* Get byte position and bit position */
+ bytepos = handle / 8;
+ bitpos = handle & 0x7;
+
+ /* See if handle avaiable */
+ if ((g_ble_ll_conn_handles[bytepos] & (1 << bitpos)) == 0) {
+ g_ble_ll_conn_handles[bytepos] |= (1 << bitpos);
+ ++g_ble_ll_conn_handles_out;
+ break;
+ }
+ }
+
+ /* We better have a free one! If not, something wrong! */
+ assert(handle < BLE_LL_CONN_CFG_MAX_CONNS);
+
+ return handle;
+}
+
static uint32_t
ble_ll_conn_calc_access_addr(void)
{
@@ -191,7 +303,7 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
we just calculate */
/* Iterate through channel map to find this channel */
cntr = 0;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; i++) {
usable_chans = conn->chanmap[i];
if (usable_chans != 0) {
mask = 0x01;
@@ -213,40 +325,129 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
/**
* Initialize the connection state machine. This is done once per connection
- * when the HCI command "create connection" is issued to the controller.
+ * when the HCI command "create connection" is issued to the controller or
+ * when a slave receives a connect request,
*
* @param connsm
*/
-void
+static void
ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
{
- /* Hop increment is a random value between 5 and 16. */
- connsm->hop_inc = (rand() % 12) + 5;
-
- /* Reset event counter */
+ /* Reset event counter and last unmapped channel; get a handle */
+ connsm->last_unmapped_chan = 0;
connsm->conn_event_cntr = 0;
+ connsm->conn_handle = ble_ll_conn_get_unused_handle();
+
+ if (hcc != NULL) {
+ /* Must be master */
+ connsm->conn_role = BLE_LL_CONN_ROLE_MASTER;
+ connsm->conn_tx_win_size = BLE_LL_CONN_CFG_TX_WIN_SIZE;
+ connsm->conn_tx_win_off = BLE_LL_CONN_CFG_TX_WIN_OFF;
+ connsm->master_sca = BLE_LL_CONN_CFG_MASTER_SCA;
+
+ /* Hop increment is a random value between 5 and 16. */
+ connsm->hop_inc = (rand() % 12) + 5;
+
+ /* Set slave latency, supervision timeout and connection interval */
+ connsm->conn_slave_latency = hcc->conn_latency;
+ connsm->conn_spvn_tmo = hcc->supervision_timeout;
+ /* XXX: for now, just make connection interval equal to max */
+ connsm->conn_itvl = hcc->conn_itvl_max;
+
+ /* Set own address type and peer address if needed */
+ connsm->own_addr_type = hcc->own_addr_type;
+ if (hcc->filter_policy == 0) {
+ memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
+ connsm->peer_addr_type = hcc->peer_addr_type;
+ }
- /* Set slave latency */
- connsm->conn_slave_latency = hcc->conn_latency;
- connsm->conn_spvn_tmo = hcc->supervision_timeout;
+ /* XXX: what to do with min/max connection event length? */
- /* Set own address type and peer address if needed */
- connsm->own_addr_type = hcc->own_addr_type;
- if (hcc->filter_policy == 0) {
- memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
- connsm->peer_addr_type = hcc->peer_addr_type;
+ /* XXX: for now, just set the channel map to all 1's. Needs to get
+ set to default or initialized or something */
+ connsm->num_used_chans = 37;
+ memset(connsm->chanmap, 0xff, BLE_LL_CONN_CHMAP_LEN - 1);
+ connsm->chanmap[4] = 0x1f;
+
+ /* Calculate random access address and crc initialization value */
+ connsm->access_addr = ble_ll_conn_calc_access_addr();
+ connsm->crcinit = rand() & 0xffffff;
+ } else {
+ connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
+ }
+}
+
+/**
+ * Send a connection complete event
+ *
+ * @param status The BLE error code associated with the event
+ */
+static void
+ble_ll_conn_comp_event_send(uint8_t status)
+{
+ uint8_t *evbuf;
+ struct ble_ll_conn_sm *connsm;
+
+ if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE - 1)) {
+ evbuf = os_memblock_get(&g_hci_cmd_pool);
+ if (evbuf) {
+ connsm = &g_ble_ll_conn_sm;
+ evbuf[0] = BLE_HCI_EVCODE_LE_META;
+ evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
+ evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+ evbuf[3] = status;
+ if (status == BLE_ERR_SUCCESS) {
+ htole16(evbuf + 4, connsm->conn_handle);
+ evbuf[6] = connsm->conn_role;
+ evbuf[7] = connsm->peer_addr_type;
+ memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
+ htole16(evbuf + 14, connsm->conn_itvl);
+ htole16(evbuf + 16, connsm->conn_slave_latency);
+ evbuf[18] = connsm->master_sca;
+ }
+
+ /* XXX: what to do if we fail to send event? */
+ ble_ll_hci_event_send(evbuf);
+ }
}
+}
+
+/**
+ * Update the connection request PDU with the address type and address of
+ * advertiser we are going to send connect request to.
+ *
+ * @param m
+ * @param adva
+ * @param addr_type
+ */
+void
+ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type)
+{
+ uint8_t pdu_type;
+ uint8_t *dptr;
- /* XXX: set connection interval */
- /* XXX: what to do with min/max connection event? */
- /* XXX: where does the channel map get set? */
+ assert(m != NULL);
- /* XXX: Calculate random access address */
- connsm->access_addr = ble_ll_conn_calc_access_addr();
+ dptr = m->om_data;
+ pdu_type = dptr[0];
+ if (addr_type) {
+ /* Set random address */
+ pdu_type |= BLE_ADV_PDU_HDR_RXADD_MASK;
+ } else {
+ /* Set public device address */
+ pdu_type &= ~BLE_ADV_PDU_HDR_RXADD_MASK;
+ }
+ dptr[0] = pdu_type;
+ memcpy(dptr + BLE_LL_CONN_REQ_ADVA_OFF, adva, BLE_DEV_ADDR_LEN);
}
+/**
+ * Make a connect request PDU
+ *
+ * @param connsm
+ */
void
-ble_ll_conn_req_make(struct ble_ll_conn_sm *connsm)
+ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
{
uint8_t pdu_type;
uint8_t *addr;
@@ -275,17 +476,25 @@ ble_ll_conn_req_make(struct ble_ll_conn_sm *connsm)
/* Construct the connect request */
dptr = m->om_data;
- dptr[0] = pdu_type; /* XXX: this can change based on advertiser addr */
+ dptr[0] = pdu_type;
dptr[1] = BLE_CONNECT_REQ_LEN;
memcpy(dptr + BLE_LL_PDU_HDR_LEN, addr, BLE_DEV_ADDR_LEN);
- /* XXX: what about this next address? I cant put this in here yet, right? */
-#if 0
- memcpy(dptr + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN, adv_addr,
- BLE_DEV_ADDR_LEN);
-#endif
- dptr += BLE_LL_PDU_HDR_LEN + (2 * BLE_DEV_ADDR_LEN);
+
+ /* Skip the advertiser's address as we dont know that yet */
+ dptr += (BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN);
/* Access address */
+ htole32(dptr, connsm->access_addr);
+ dptr[4] = connsm->crcinit >> 16;
+ dptr[5] = connsm->crcinit >> 8;
+ dptr[6] = (uint8_t)connsm->crcinit;
+ dptr[7] = connsm->conn_tx_win_size;
+ htole16(dptr + 8, connsm->conn_tx_win_off);
+ htole16(dptr + 10, connsm->conn_itvl);
+ htole16(dptr + 12, connsm->conn_slave_latency);
+ htole16(dptr + 14, connsm->conn_spvn_tmo);
+ memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CONN_CHMAP_LEN);
+ dptr[21] = connsm->hop_inc | connsm->master_sca;
}
/**
@@ -304,6 +513,13 @@ ble_ll_conn_create(uint8_t *cmdbuf)
struct hci_create_conn *hcc;
struct ble_ll_conn_sm *connsm;
+ /* XXX: what happens if we have too many! Do something about this */
+
+ /*
+ * XXX: right now, we only allow one connection, so if the connection
+ * state machine is used we return error. Otherewise, we would only need
+ * to check the scanner. If it is enabled, it means we are initiating.
+ */
/* If already enabled, we return an error */
connsm = &g_ble_ll_conn_sm;
if (ble_ll_scan_enabled() || (connsm->conn_state != BLE_LL_CONN_STATE_IDLE)) {
@@ -381,25 +597,311 @@ ble_ll_conn_create(uint8_t *cmdbuf)
return BLE_ERR_INV_HCI_CMD_PARMS;
}
- /* Set state machine parameters */
- ble_ll_scan_initiator_start(hcc);
-
- /* XXX: I have not dealt with lots of the state machine parameters! */
-
/* Initialize the connection sm */
ble_ll_conn_sm_init(connsm, hcc);
/* Create the connection request */
- ble_ll_conn_req_make(connsm);
+ ble_ll_conn_req_pdu_make(connsm);
- /* XXX: gotta start scanning! */
-
- return BLE_ERR_SUCCESS;
+ /* Start scanning */
+ return ble_ll_scan_initiator_start(hcc);
}
+/**
+ * Called when HCI command to cancel a create connection command has been
+ * received.
+ *
+ * Context: Link Layer (HCI command parser)
+ *
+ * @return int
+ */
int
ble_ll_conn_create_cancel(void)
{
- /* XXX: implement this */
- return BLE_ERR_SUCCESS;
+ int rc;
+
+ /*
+ * If we receive this command and we have not got a connection
+ * create command, we have to return disallowed. The spec does not say
+ * what happens if the connection has already been established.
+ */
+ if (ble_ll_scan_enabled()) {
+ /* stop scanning */
+ ble_ll_scan_sm_stop(ble_ll_scan_sm_get());
+
+ /* XXX: what to do with connection state machine? */
+
+ /* Send connection complete event */
+ ble_ll_conn_comp_event_send(BLE_ERR_UNK_CONN_ID);
+ rc = BLE_ERR_SUCCESS;
+ } else {
+ /* If we have established connection or we are idle do not allow */
+ rc = BLE_ERR_CMD_DISALLOWED;
+ }
+
+ return rc;
+}
+
+/* Returns true if the address matches the connection peer address */
+int
+ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
+{
+ int rc;
+ struct ble_ll_conn_sm *connsm;
+
+ rc = 0;
+ connsm = &g_ble_ll_conn_sm;
+ if ((connsm->peer_addr_type == addr_type) &&
+ !memcmp(adva, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
+ rc = 1;
+ }
+
+ return rc;
+}
+
+/**
+ * Send a connection requestion to an advertiser
+ *
+ * @param addr_type Address type of advertiser
+ * @param adva Address of advertiser
+ */
+int
+ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva)
+{
+ int rc;
+ struct os_mbuf *m;
+ struct ble_ll_conn_sm *connsm;
+
+ m = ble_ll_scan_get_pdu();
+ ble_ll_conn_req_pdu_update(m, adva, addr_type);
+ rc = ble_phy_tx(m, BLE_PHY_TRANSITION_RX_TX, BLE_PHY_TRANSITION_NONE);
+ if (!rc) {
+ connsm = &g_ble_ll_conn_sm;
+ connsm->peer_addr_type = addr_type;
+ memcpy(connsm->peer_addr, adva, BLE_DEV_ADDR_LEN);
+ connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
+ }
+
+ return rc;
+}
+
+/**
+ * Process a received PDU while in the initiating state.
+ *
+ * Context: Link Layer task.
+ *
+ * @param pdu_type
+ * @param rxbuf
+ */
+void
+ble_ll_init_rx_pdu_proc(uint8_t pdu_type, uint8_t *rxbuf, uint8_t crcok)
+{
+ struct ble_ll_scan_sm *scansm;
+ struct ble_ll_conn_sm *connsm;
+
+ /* XXX: Do I care what pdu type I receive? Not sure exactly how to
+ deal with knowing a connection request was sent. */
+
+ /*
+ * XXX: Not sure I like this but I will deal with it for now. Just
+ * check the connection state machine. If state is created, we move
+ * to the connected state.
+ */
+ connsm = &g_ble_ll_conn_sm;
+ if (crcok && (connsm->conn_state == BLE_LL_CONN_STATE_CREATED)) {
+ /* Stop scanning */
+ scansm = ble_ll_scan_sm_get();
+ ble_ll_scan_sm_stop(scansm);
+
+ /* We are now in connection state */
+ ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+
+ /* Send connection complete event */
+ ble_ll_conn_comp_event_send(BLE_ERR_SUCCESS);
+ } else {
+ /* We need to re-enable the PHY if we are in idle state */
+ if (ble_phy_state_get() == BLE_PHY_STATE_IDLE) {
+ /* XXX: If this returns error, we will need to attempt to
+ re-start scanning! */
+ ble_phy_rx();
+ }
+ }
+}
+
+/**
+ * Called when a receive PDU has ended.
+ *
+ * Context: Interrupt
+ *
+ * @param rxpdu
+ *
+ * @return int
+ * < 0: Disable the phy after reception.
+ * == 0: Success. Do not disable the PHY.
+ * > 0: Do not disable PHY as that has already been done.
+ */
+int
+ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
+{
+ int rc;
+ int chk_send_req;
+ uint8_t pdu_type;
+ uint8_t addr_type;
+ uint8_t *adv_addr;
+ uint8_t *init_addr;
+ uint8_t *rxbuf;
+ struct ble_mbuf_hdr *ble_hdr;
+
+ /* Only interested in ADV IND or ADV DIRECT IND */
+ rxbuf = rxpdu->om_data;
+ pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
+
+ switch (pdu_type) {
+ case BLE_ADV_PDU_TYPE_ADV_IND:
+ chk_send_req = 1;
+ break;
+ case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
+ init_addr = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
+ addr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
+ if (ble_ll_is_our_devaddr(init_addr, addr_type)) {
+ chk_send_req = 1;
+ } else {
+ chk_send_req = 0;
+ }
+ break;
+ default:
+ chk_send_req = 0;
+ break;
+ }
+
+ /* Should we send a connect request? */
+ rc = -1;
+ if (chk_send_req) {
+ /* Check filter policy */
+ adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
+ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+ addr_type = BLE_ADDR_TYPE_RANDOM;
+ } else {
+ addr_type = BLE_ADDR_TYPE_PUBLIC;
+ }
+
+ /* Check filter policy */
+ if (ble_ll_scan_whitelist_enabled()) {
+ /* Check if device is on whitelist. If not, leave */
+ if (!ble_ll_whitelist_match(adv_addr, addr_type)) {
+ return -1;
+ }
+
+ /* Set BLE mbuf header flags */
+ ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+ ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
+ } else {
+ /* XXX: Resolvable? Deal with those */
+ /* XXX: HW device matching? If so, implement */
+ /* Must match the connection address */
+ if (!ble_ll_conn_is_peer_adv(addr_type, adv_addr)) {
+ return -1;
+ }
+ }
+
+ /* Setup to transmit the connect request */
+ rc = ble_ll_conn_request_send(addr_type, adv_addr);
+ }
+
+ return rc;
+}
+
+/**
+ * Called on pdu start (by link layer) when in initiating state.
+ *
+ * @param pdu_type
+ *
+ * @return int
+ */
+int
+ble_ll_init_rx_pdu_start(uint8_t pdu_type)
+{
+ int rc;
+
+ /* We might respond to adv ind or adv direct ind only */
+ rc = 0;
+ if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
+ (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND)) {
+ rc = 1;
+ }
+
+ return rc;
+}
+
+/**
+ * Called when a device has received a connect request while advertising and
+ * the connect request has passed the advertising filter policy and is for
+ * us. This will start a connection in the slave role.
+ *
+ * @param rxbuf Pointer to received PDU
+ */
+void
+ble_ll_conn_slave_start(uint8_t *rxbuf)
+{
+ uint32_t crcinit;
+ uint8_t *dptr;
+ struct ble_ll_conn_sm *connsm;
+
+ /* XXX: Should we error check the parameters? */
+
+ /* Set the pointer at the start of the connection data */
+ dptr = rxbuf + BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN;
+
+ connsm = &g_ble_ll_conn_sm;
+ connsm->access_addr = le32toh(dptr);
+ crcinit = dptr[4];
+ crcinit <<= 16;
+ crcinit |= dptr[5];
+ crcinit <<= 8;
+ crcinit |= dptr[6];
+ connsm->crcinit = crcinit;
+ connsm->conn_tx_win_size = dptr[7];
+ connsm->conn_tx_win_off = le16toh(dptr + 8);
+ connsm->conn_itvl = le16toh(dptr + 10);
+ connsm->conn_slave_latency = le16toh(dptr + 12);
+ connsm->conn_spvn_tmo = le16toh(dptr + 14);
+ memcpy(&connsm->chanmap, dptr + 16, BLE_LL_CONN_CHMAP_LEN);
+ connsm->hop_inc = dptr[21] & 0x1F;
+ connsm->master_sca = dptr[21] >> 5;
+
+ /* Set the address of device that we are connecting with */
+ memcpy(&connsm->peer_addr, rxbuf + BLE_LL_PDU_HDR_LEN, BLE_DEV_ADDR_LEN);
+ if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+ connsm->peer_addr_type = BLE_ADDR_TYPE_RANDOM;
+ } else {
+ connsm->peer_addr_type = BLE_ADDR_TYPE_PUBLIC;
+ }
+
+ connsm->num_used_chans = ble_ll_conn_calc_used_chans(connsm->chanmap);
+
+ /* Need to initialize the connection state machine */
+ ble_ll_conn_sm_init(connsm, NULL);
+
+ /* Set connection state to created */
+ connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
+
+ /* Set state to connection */
+ ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+
+ /* Send connection complete event */
+ ble_ll_conn_comp_event_send(BLE_ERR_SUCCESS);
+}
+
+/* Initializet the connection module */
+void
+ble_ll_conn_init(void)
+{
+ int rc;
+
+ /* Create connection memory pool */
+ rc = os_mempool_init(&g_ble_ll_conn_pool, BLE_LL_CONN_CFG_MAX_CONNS,
+ sizeof(struct ble_ll_conn_sm), &g_ble_ll_conn_buf,
+ "LLConnPool");
+
+ assert(rc == 0);
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index f344d87..98f9307 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -246,6 +246,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
if (len == BLE_HCI_CREATE_CONN_LEN) {
rc = ble_ll_conn_create(cmdbuf);
}
+ /* This is a hack; command status gets sent instead of cmd complete */
rc += (BLE_ERR_MAX + 1);
break;
case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c
index 05416a4..aaeab1b 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -52,32 +52,6 @@
* code might be made simpler.
*/
-/* Scanning state machine */
-struct ble_ll_scan_sm
-{
- uint8_t scan_enabled;
- uint8_t scan_type;
- uint8_t own_addr_type;
- uint8_t scan_chan;
- uint8_t scan_filt_policy;
- uint8_t scan_filt_dups;
- uint8_t scan_rsp_pending;
- uint8_t scan_rsp_cons_fails;
- uint8_t scan_rsp_cons_ok;
- uint16_t upper_limit;
- uint16_t backoff_count;
- uint16_t scan_itvl;
- uint16_t scan_window;
- uint32_t scan_win_start_time;
- struct os_mbuf *scan_req_pdu;
- struct os_event scan_win_end_ev;
-};
-
-/* Scan types */
-#define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE)
-#define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE)
-#define BLE_SCAN_TYPE_INITIATE (2)
-
/* The scanning state machine global object */
struct ble_ll_scan_sm g_ble_ll_scan_sm;
@@ -421,7 +395,6 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
adv_data_len -= BLE_DEV_ADDR_LEN;
}
- rc = BLE_ERR_MEM_CAPACITY;
if (ble_ll_hci_is_le_event_enabled(subev - 1)) {
evbuf = os_memblock_get(&g_hci_cmd_pool);
if (evbuf) {
@@ -552,7 +525,11 @@ ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
rc = BLE_LL_SCHED_STATE_DONE;
} else {
/* Set link layer state to scanning */
- ble_ll_state_set(BLE_LL_STATE_SCANNING);
+ if (g_ble_ll_scan_sm.scan_type == BLE_SCAN_TYPE_INITIATE) {
+ ble_ll_state_set(BLE_LL_STATE_INITIATING);
+ } else {
+ ble_ll_state_set(BLE_LL_STATE_SCANNING);
+ }
/* Set end time to end of scan window */
sch->next_wakeup = sch->end_time;
@@ -564,13 +541,9 @@ ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
}
/**
- * ll scan sm stop
- *
* Stop the scanning state machine
- *
- * @param scansm Pointer to scanning state machine.
*/
-static void
+void
ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
{
/* XXX: Stop any timers we may have started */
@@ -578,9 +551,6 @@ ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
/* Remove any scheduled advertising items */
ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_SCAN);
- /* Disable the PHY */
- ble_phy_disable();
-
/* Disable whitelisting (just in case) */
ble_ll_whitelist_disable();
@@ -676,7 +646,7 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
assert(0);
}
- return 0;
+ return BLE_ERR_SUCCESS;
}
void
@@ -755,19 +725,17 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
int rc;
struct ble_ll_scan_sm *scansm;
- /*
- * If there is a chance that we will respond to the PDU we must
- * return the appropriate value so that the PHY goes from rx to tx.
- */
rc = 0;
scansm = &g_ble_ll_scan_sm;
- if (scansm->scan_type == BLE_SCAN_TYPE_ACTIVE) {
+
+ switch (scansm->scan_type) {
+ case BLE_SCAN_TYPE_ACTIVE:
+ /* If adv ind or scan ind, we may send scan request */
if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
(pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)) {
rc = 1;
}
- /* XXX: could post event here to LL task to do the backoff... */
/*
* If there is a scan response pending, it means that we did
* not receive a scan response to our previous request unless
@@ -778,6 +746,10 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
ble_ll_scan_req_backoff(scansm, 0);
}
}
+ break;
+ case BLE_SCAN_TYPE_PASSIVE:
+ default:
+ break;
}
/*
@@ -792,7 +764,6 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
return rc;
}
-
/*
* NOTE: If this returns a positive number there was an error but
* there is no need to disable the PHY on return as that was
@@ -1078,6 +1049,11 @@ ble_ll_scan_set_enable(uint8_t *cmd)
}
} else {
if (scansm->scan_enabled) {
+ /* XXX: what happens if a receive has started? What about
+ * the phy pdu? Do we need to do anything with it? The rx pdu
+ at the phy??? Keep it there? */
+ /* Disable the PHY */
+ ble_phy_disable();
ble_ll_scan_sm_stop(scansm);
}
}
@@ -1107,7 +1083,7 @@ ble_ll_scan_can_chg_whitelist(void)
return rc;
}
-void
+int
ble_ll_scan_initiator_start(struct hci_create_conn *hcc)
{
struct ble_ll_scan_sm *scansm;
@@ -1118,6 +1094,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc)
scansm->scan_window = hcc->scan_window;
scansm->scan_filt_policy = hcc->filter_policy;
scansm->own_addr_type = hcc->own_addr_type;
+ return ble_ll_scan_sm_start(scansm);
}
/**
@@ -1138,6 +1115,20 @@ ble_ll_scan_get_pdu(void)
return g_ble_ll_scan_sm.scan_req_pdu;
}
+/* Returns the global scanning state machine */
+struct ble_ll_scan_sm *
+ble_ll_scan_sm_get(void)
+{
+ return &g_ble_ll_scan_sm;
+}
+
+/* Returns true if whitelist is enabled for scanning */
+int
+ble_ll_scan_whitelist_enabled(void)
+{
+ return g_ble_ll_scan_sm.scan_filt_policy & 1;
+}
+
/**
* ble ll scan init
*
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/drivers/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/nrf52/src/ble_phy.c b/net/nimble/drivers/nrf52/src/ble_phy.c
index 4713c39..cd5549d 100644
--- a/net/nimble/drivers/nrf52/src/ble_phy.c
+++ b/net/nimble/drivers/nrf52/src/ble_phy.c
@@ -23,6 +23,11 @@
#include "controller/ble_ll.h"
#include "mcu/nrf52_bitfields.h"
+/*
+ * XXX: TODO
+ * 1) make phy rx start and end function pointers to call?
+ */
+
/* To disable all radio interrupts */
#define NRF52_RADIO_IRQ_MASK_ALL (0x34FF)