You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/01/14 00:24:30 UTC
[3/3] incubator-mynewt-larva git commit: GAP Auto Connection
Establishment procedure.
GAP Auto Connection Establishment procedure.
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/ca671d23
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/ca671d23
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/ca671d23
Branch: refs/heads/master
Commit: ca671d23694e97280816b1c97acdeabb20387cfb
Parents: b2fde97
Author: Christopher Collins <cc...@gmail.com>
Authored: Tue Jan 12 19:20:25 2016 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Jan 13 15:24:08 2016 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/ble_gap.h | 7 +
net/nimble/host/include/host/ble_hs_test.h | 1 +
net/nimble/host/src/ble_gap_conn.c | 290 +++++++++++++++++++--
net/nimble/host/src/test/ble_gap_test.c | 284 ++++++++++++++++++++
net/nimble/host/src/test/ble_gatt_read_test.c | 10 +-
net/nimble/host/src/test/ble_hs_test.c | 1 +
net/nimble/host/src/test/ble_hs_test_util.c | 20 ++
net/nimble/host/src/test/ble_hs_test_util.h | 2 +
8 files changed, 582 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/include/host/ble_gap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gap.h b/net/nimble/host/include/host/ble_gap.h
index 589f049..54f34d0 100644
--- a/net/nimble/host/include/host/ble_gap.h
+++ b/net/nimble/host/include/host/ble_gap.h
@@ -77,11 +77,18 @@ typedef void ble_gap_connect_fn(struct ble_gap_conn_event *event, void *arg);
#define BLE_GAP_DISC_MODE_LTD 2
#define BLE_GAP_DISC_MODE_GEN 3
+struct ble_gap_white_entry {
+ uint8_t addr_type;
+ uint8_t addr[6];
+};
+
void ble_gap_conn_set_cb(ble_gap_connect_fn *cb, void *arg);
int ble_gap_conn_advertise(uint8_t discoverable_mode, uint8_t connectable_mode,
uint8_t *peer_addr, uint8_t peer_addr_type);
int ble_gap_conn_set_adv_fields(struct ble_hs_adv_fields *adv_fields);
int ble_gap_conn_disc(uint32_t duration_ms, uint8_t discovery_mode);
+int ble_gap_conn_auto_connect(struct ble_gap_white_entry *white_list,
+ int white_list_count);
int ble_gap_conn_direct_connect(int addr_type, uint8_t *addr);
int ble_gap_conn_terminate(uint16_t handle);
int ble_gap_conn_cancel(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/include/host/ble_hs_test.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_hs_test.h b/net/nimble/host/include/host/ble_hs_test.h
index 39de412..746087f 100644
--- a/net/nimble/host/include/host/ble_hs_test.h
+++ b/net/nimble/host/include/host/ble_hs_test.h
@@ -40,5 +40,6 @@ int ble_hs_adv_test_all(void);
int ble_gatts_reg_test_all(void);
int ble_gatts_notify_test_all(void);
int ble_gatt_find_s_test_all(void);
+int ble_gap_test_all(void);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/ble_gap_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap_conn.c b/net/nimble/host/src/ble_gap_conn.c
index e853b5d..5ef9c29 100644
--- a/net/nimble/host/src/ble_gap_conn.c
+++ b/net/nimble/host/src/ble_gap_conn.c
@@ -28,6 +28,11 @@
#include "ble_gatt_priv.h"
#include "ble_gap_conn.h"
+#define BLE_GAP_CONN_M_PROC_NULL 0
+#define BLE_GAP_CONN_M_PROC_DISC 1
+#define BLE_GAP_CONN_M_PROC_CONN_AUTO 2
+#define BLE_GAP_CONN_M_PROC_CONN_DIR 3
+
#define BLE_GAP_CONN_STATE_IDLE UINT8_MAX
/** General discovery master states. */
@@ -36,9 +41,15 @@
#define BLE_GAP_CONN_M_STATE_DISC_ACKED 2
/** General discovery master states. */
-#define BLE_GAP_CONN_M_STATE_DIRECT_PENDING 3
-#define BLE_GAP_CONN_M_STATE_DIRECT_UNACKED 4
-#define BLE_GAP_CONN_M_STATE_DIRECT_ACKED 5
+#define BLE_GAP_CONN_M_STATE_AUTO_CLEAR_WL 3
+#define BLE_GAP_CONN_M_STATE_AUTO_ADD_WL 4
+#define BLE_GAP_CONN_M_STATE_AUTO_CREATE 5
+#define BLE_GAP_CONN_M_STATE_AUTO_ACKED 6
+
+/** General discovery master states. */
+#define BLE_GAP_CONN_M_STATE_DIRECT_PENDING 7
+#define BLE_GAP_CONN_M_STATE_DIRECT_UNACKED 8
+#define BLE_GAP_CONN_M_STATE_DIRECT_ACKED 9
/** Undirected slave states. */
#define BLE_GAP_CONN_S_STATE_UND_PARAMS 0
@@ -81,8 +92,8 @@
/** 10.24 seconds. */
#define BLE_GAP_GEN_DISC_SCAN_MIN (10.24 * 1000)
-#define BLE_GAP_CONN_MODE_MAX 4
-#define BLE_GAP_DISC_MODE_MAX 4
+#define BLE_GAP_CONN_MODE_MAX 4
+#define BLE_GAP_DISC_MODE_MAX 4
/**
* The maximum amount of user data that can be put into the advertising data.
@@ -96,6 +107,7 @@ static int ble_gap_conn_adv_power_tx(void *arg);
static int ble_gap_conn_adv_data_tx(void *arg);
static int ble_gap_conn_adv_rsp_data_tx(void *arg);
static int ble_gap_conn_adv_enable_tx(void *arg);
+static int ble_gap_conn_auto_tx_add_wl(void *arg);
static ble_hci_sched_tx_fn * const
ble_gap_conn_slave_dispatch[BLE_GAP_CONN_S_STATE_MAX] = {
@@ -111,6 +123,7 @@ static ble_hci_sched_tx_fn * const
static uint8_t ble_gap_conn_s_conn_mode;
static uint8_t ble_gap_conn_s_disc_mode;
+static uint8_t ble_gap_conn_m_proc;
static uint8_t ble_gap_conn_m_disc_mode;
static struct hci_adv_params ble_gap_conn_adv_params;
@@ -126,12 +139,13 @@ static uint8_t ble_gap_conn_master_addr[BLE_DEV_ADDR_LEN];
static uint8_t ble_gap_conn_slave_addr[BLE_DEV_ADDR_LEN];
static uint8_t ble_gap_conn_adv_data_len;
static uint8_t ble_gap_conn_adv_data[BLE_HCI_MAX_ADV_DATA_LEN];
+static struct ble_gap_white_entry *ble_gap_conn_white_list;
+static int ble_gap_conn_white_list_count;
+static int ble_gap_conn_white_list_cur;
static int8_t ble_gap_conn_tx_pwr_lvl;
static struct os_callout_func ble_gap_conn_master_timer;
static struct os_callout_func ble_gap_conn_slave_timer;
-/* XXX: Need to clear slave mode when we join a master. */
-
/*****************************************************************************
* $misc *
*****************************************************************************/
@@ -214,6 +228,8 @@ static void
ble_gap_conn_master_reset_state(void)
{
ble_gap_conn_master_state = BLE_GAP_CONN_STATE_IDLE;
+ ble_gap_conn_m_proc = BLE_GAP_CONN_M_PROC_NULL;
+ ble_gap_conn_m_disc_mode = BLE_GAP_DISC_MODE_NULL;
}
static void
@@ -234,23 +250,21 @@ ble_gap_conn_master_failed(int status)
{
struct ble_gap_conn_event event;
- uint8_t old_state;
+ uint8_t old_proc;
os_callout_stop(&ble_gap_conn_master_timer.cf_c);
- old_state = ble_gap_conn_master_state;
+ old_proc = ble_gap_conn_m_proc;
ble_gap_conn_master_reset_state();
- switch (old_state) {
- case BLE_GAP_CONN_M_STATE_DISC_PARAMS:
- case BLE_GAP_CONN_M_STATE_DISC_ACKED:
+ switch (old_proc) {
+ case BLE_GAP_CONN_M_PROC_DISC:
event.type = BLE_GAP_CONN_EVENT_TYPE_SCAN_DONE;
ble_gap_conn_call_cb(&event);
break;
- case BLE_GAP_CONN_M_STATE_DIRECT_PENDING:
- case BLE_GAP_CONN_M_STATE_DIRECT_UNACKED:
- case BLE_GAP_CONN_M_STATE_DIRECT_ACKED:
+ case BLE_GAP_CONN_M_PROC_CONN_AUTO:
+ case BLE_GAP_CONN_M_PROC_CONN_DIR:
ble_gap_conn_notify_connect(status, NULL);
break;
@@ -299,7 +313,7 @@ ble_gap_conn_rx_disconn_complete(struct hci_disconn_complete *evt)
int
ble_gap_conn_master_in_progress(void)
{
- return ble_gap_conn_master_state != BLE_GAP_CONN_STATE_IDLE;
+ return ble_gap_conn_m_proc != BLE_GAP_CONN_M_PROC_NULL;
}
/**
@@ -311,6 +325,25 @@ ble_gap_conn_slave_in_progress(void)
return ble_gap_conn_slave_state != BLE_GAP_CONN_STATE_IDLE;
}
+static int
+ble_gap_conn_master_enqueue(int state, int in_progress,
+ ble_hci_sched_tx_fn *hci_tx_cb, void *cb_arg)
+{
+ int rc;
+
+ ble_gap_conn_master_state = state;
+ rc = ble_hci_sched_enqueue(hci_tx_cb, cb_arg);
+ if (rc != 0) {
+ if (in_progress) {
+ ble_gap_conn_master_failed(rc);
+ } else {
+ ble_gap_conn_master_reset_state();
+ }
+ }
+
+ return rc;
+}
+
/**
* Attempts to complete the master connection process in response to a
* "connection complete" event from the controller. If the master connection
@@ -330,6 +363,8 @@ ble_gap_conn_slave_in_progress(void)
static int
ble_gap_conn_accept_master_conn(uint8_t addr_type, uint8_t *addr)
{
+ int i;
+
switch (ble_gap_conn_master_state) {
case BLE_GAP_CONN_M_STATE_DIRECT_ACKED:
/* XXX: Check address type. */
@@ -338,6 +373,27 @@ ble_gap_conn_accept_master_conn(uint8_t addr_type, uint8_t *addr)
ble_gap_conn_master_reset_state();
return 0;
}
+
+ case BLE_GAP_CONN_M_STATE_AUTO_ACKED:
+ for (i = 0; i < ble_gap_conn_white_list_count; i++) {
+ if (addr_type == ble_gap_conn_white_list[i].addr_type &&
+ memcmp(addr, ble_gap_conn_white_list[i].addr,
+ BLE_DEV_ADDR_LEN) == 0) {
+
+ break;
+ }
+ }
+ if (i == ble_gap_conn_white_list_count) {
+ ble_gap_conn_master_failed(BLE_HS_ECONTROLLER);
+ return BLE_HS_ECONTROLLER;
+ } else {
+ os_callout_stop(&ble_gap_conn_master_timer.cf_c);
+ ble_gap_conn_master_reset_state();
+ return 0;
+ }
+
+ default:
+ break;
}
return BLE_HS_ENOENT;
@@ -464,7 +520,7 @@ ble_gap_conn_rx_conn_complete(struct hci_le_conn_complete *evt)
if (rc == 0) {
ble_gap_conn_master_reset_state();
} else {
- return BLE_HS_ENOENT;
+ return rc;
}
break;
@@ -474,7 +530,7 @@ ble_gap_conn_rx_conn_complete(struct hci_le_conn_complete *evt)
if (rc == 0) {
ble_gap_conn_slave_reset_state();
} else {
- return BLE_HS_ENOENT;
+ return rc;
}
break;
@@ -833,8 +889,8 @@ ble_gap_conn_adv_initiate(void)
* modes, specify 0. For directed connectable
* mode, this should be one of the following
* constants:
- * o BLE_HCI_ADV_PEER_ADDR_PUBLIC
- * o BLE_HCI_ADV_PEER_ADDR_RANDOM
+ * o BLE_HCI_ADV_PEER_ADDR_PUBLIC
+ * o BLE_HCI_ADV_PEER_ADDR_RANDOM
*
* @return 0 on success; nonzero on failure.
*/
@@ -903,7 +959,7 @@ ble_gap_conn_set_adv_fields(struct ble_hs_adv_fields *adv_fields)
}
/*****************************************************************************
- * $general discovery procedure *
+ * $discovery procedures *
*****************************************************************************/
static void
@@ -1002,14 +1058,13 @@ ble_gap_conn_disc(uint32_t duration_ms, uint8_t discovery_mode)
duration_ms = BLE_GAP_GEN_DISC_SCAN_MIN;
}
- ble_gap_conn_master_state = BLE_GAP_CONN_M_STATE_DISC_PARAMS;
memset(ble_gap_conn_master_addr, 0, BLE_DEV_ADDR_LEN);
ble_gap_conn_m_disc_mode = discovery_mode;
-
- rc = ble_hci_sched_enqueue(ble_gap_conn_disc_tx_params, NULL);
+ ble_gap_conn_m_proc = BLE_GAP_CONN_M_PROC_DISC;
+ rc = ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_DISC_PARAMS, 0,
+ ble_gap_conn_disc_tx_params, NULL);
if (rc != 0) {
- ble_gap_conn_master_reset_state();
return rc;
}
@@ -1020,6 +1075,183 @@ ble_gap_conn_disc(uint32_t duration_ms, uint8_t discovery_mode)
}
/*****************************************************************************
+ * $auto connection establishment procedure *
+ *****************************************************************************/
+
+/**
+ * Processes an HCI acknowledgement (either command status or command complete)
+ * while a master connection is being established.
+ */
+static void
+ble_gap_conn_auto_ack_create(struct ble_hci_ack *ack, void *arg)
+{
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_CREATE);
+
+ if (ack->bha_status != 0) {
+ ble_gap_conn_master_failed(ack->bha_status);
+ return;
+ }
+
+ ble_gap_conn_master_state = BLE_GAP_CONN_M_STATE_AUTO_ACKED;
+}
+
+static int
+ble_gap_conn_auto_tx_create(void *arg)
+{
+ struct hci_create_conn hcc;
+ int rc;
+
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_CREATE);
+
+ hcc.scan_itvl = 0x0010;
+ hcc.scan_window = 0x0010;
+ hcc.filter_policy = BLE_HCI_CONN_FILT_NO_WL;
+ hcc.peer_addr_type = BLE_HCI_ADV_PEER_ADDR_PUBLIC;
+ memcpy(hcc.peer_addr, ble_gap_conn_master_addr, sizeof hcc.peer_addr);
+ hcc.own_addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
+ hcc.conn_itvl_min = 24;
+ hcc.conn_itvl_max = 40;
+ hcc.conn_latency = 0;
+ hcc.supervision_timeout = 0x0100; // XXX
+ hcc.min_ce_len = 0x0010; // XXX
+ hcc.max_ce_len = 0x0300; // XXX
+
+ ble_hci_ack_set_callback(ble_gap_conn_auto_ack_create, NULL);
+
+ rc = host_hci_cmd_le_create_connection(&hcc);
+ if (rc != 0) {
+ ble_gap_conn_master_failed(rc);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+ble_gap_conn_auto_ack_add_wl(struct ble_hci_ack *ack, void *arg)
+{
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_ADD_WL);
+
+ if (ack->bha_status != 0) {
+ ble_gap_conn_master_failed(ack->bha_status);
+ return;
+ }
+
+ ble_gap_conn_white_list_cur++;
+ if (ble_gap_conn_white_list_cur < ble_gap_conn_white_list_count) {
+ ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_AUTO_ADD_WL, 1,
+ ble_gap_conn_auto_tx_add_wl, NULL);
+ } else {
+ ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_AUTO_CREATE, 1,
+ ble_gap_conn_auto_tx_create, NULL);
+ }
+}
+
+static int
+ble_gap_conn_auto_tx_add_wl(void *arg)
+{
+ struct ble_gap_white_entry *white_entry;
+ int rc;
+
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_ADD_WL);
+ assert(ble_gap_conn_white_list != NULL);
+ assert(ble_gap_conn_white_list_cur < ble_gap_conn_white_list_count);
+
+ ble_hci_ack_set_callback(ble_gap_conn_auto_ack_add_wl, NULL);
+
+ white_entry = ble_gap_conn_white_list + ble_gap_conn_white_list_cur;
+ rc = host_hci_cmd_le_add_to_whitelist(white_entry->addr,
+ white_entry->addr_type);
+ if (rc != 0) {
+ ble_gap_conn_master_failed(rc);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+ble_gap_conn_auto_ack_clear_wl(struct ble_hci_ack *ack, void *arg)
+{
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_CLEAR_WL);
+
+ if (ack->bha_status != 0) {
+ ble_gap_conn_master_failed(ack->bha_status);
+ return;
+ }
+
+ ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_AUTO_ADD_WL, 1,
+ ble_gap_conn_auto_tx_add_wl, NULL);
+}
+
+static int
+ble_gap_conn_auto_tx_clear_wl(void *arg)
+{
+ int rc;
+
+ assert(ble_gap_conn_master_state == BLE_GAP_CONN_M_STATE_AUTO_CLEAR_WL);
+
+ ble_hci_ack_set_callback(ble_gap_conn_auto_ack_clear_wl, NULL);
+
+ rc = host_hci_cmd_le_clear_whitelist();
+ if (rc != 0) {
+ ble_gap_conn_master_failed(rc);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Performs the Auto Connection Establishment Procedure, as described in
+ * vol. 3, part C, section 9.3.5.
+ *
+ * @param addr_type The peer's address type; one of:
+ * o BLE_HCI_ADV_PEER_ADDR_PUBLIC
+ * o BLE_HCI_ADV_PEER_ADDR_RANDOM
+ * o BLE_HCI_ADV_PEER_ADDR_PUBLIC_IDENT
+ * o BLE_HCI_ADV_PEER_ADDR_RANDOM_IDENT
+ * @param addr The address of the peer to connect to.
+ *
+ * @return 0 on success; nonzero on failure.
+ */
+int
+ble_gap_conn_auto_connect(struct ble_gap_white_entry *white_list,
+ int white_list_count)
+{
+ int rc;
+ int i;
+
+ /* Make sure no master connection attempt is already in progress. */
+ if (ble_gap_conn_master_in_progress()) {
+ return BLE_HS_EALREADY;
+ }
+
+ if (white_list_count <= 0) {
+ return BLE_HS_EINVAL;
+ }
+
+ /* XXX: Verify white list not too large. */
+
+ for (i = 0; i < white_list_count; i++) {
+ if (white_list[i].addr_type != BLE_ADDR_TYPE_PUBLIC &&
+ white_list[i].addr_type != BLE_ADDR_TYPE_RANDOM) {
+
+ return BLE_HS_EINVAL;
+ }
+ }
+
+ ble_gap_conn_white_list = white_list;
+ ble_gap_conn_white_list_count = white_list_count;
+ ble_gap_conn_white_list_cur = 0;
+
+ ble_gap_conn_m_proc = BLE_GAP_CONN_M_PROC_CONN_AUTO;
+ rc = ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_AUTO_CLEAR_WL, 0,
+ ble_gap_conn_auto_tx_clear_wl, NULL);
+ return rc;
+}
+
+/*****************************************************************************
* $direct connection establishment procedure *
*****************************************************************************/
@@ -1097,13 +1329,13 @@ ble_gap_conn_direct_connect(int addr_type, uint8_t *addr)
return BLE_HS_EALREADY;
}
- ble_gap_conn_master_state = BLE_GAP_CONN_M_STATE_DIRECT_PENDING;
ble_gap_conn_master_addr_type = addr_type;
memcpy(ble_gap_conn_master_addr, addr, BLE_DEV_ADDR_LEN);
- rc = ble_hci_sched_enqueue(ble_gap_conn_direct_connect_tx, NULL);
+ ble_gap_conn_m_proc = BLE_GAP_CONN_M_PROC_CONN_DIR;
+ rc = ble_gap_conn_master_enqueue(BLE_GAP_CONN_M_STATE_DIRECT_PENDING, 0,
+ ble_gap_conn_direct_connect_tx, NULL);
if (rc != 0) {
- ble_gap_conn_master_reset_state();
return rc;
}
@@ -1231,6 +1463,8 @@ ble_gap_conn_init(void)
ble_gap_conn_cb = NULL;
ble_gap_conn_s_conn_mode = BLE_GAP_CONN_MODE_NULL;
ble_gap_conn_s_disc_mode = BLE_GAP_DISC_MODE_NULL;
+ ble_gap_conn_m_proc = BLE_GAP_CONN_M_PROC_NULL;
+ ble_gap_conn_m_disc_mode = BLE_GAP_DISC_MODE_NULL;
ble_gap_conn_master_state = BLE_GAP_CONN_STATE_IDLE;
ble_gap_conn_slave_state = BLE_GAP_CONN_STATE_IDLE;
memset(ble_gap_conn_master_addr, 0, sizeof ble_gap_conn_master_addr);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/test/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
new file mode 100644
index 0000000..4d34d47
--- /dev/null
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -0,0 +1,284 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed 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.
+ */
+
+#include <string.h>
+#include <errno.h>
+#include "testutil/testutil.h"
+#include "nimble/ble.h"
+#include "nimble/hci_common.h"
+#include "ble_hs_priv.h"
+#include "host/ble_hs_test.h"
+#include "ble_hs_conn.h"
+#include "ble_hci_sched.h"
+#include "ble_gatt_priv.h"
+#include "ble_gap_conn.h"
+#include "ble_hs_test_util.h"
+
+struct ble_gap_conn_event ble_gap_test_conn_event;
+
+static void
+ble_gap_test_misc_connect_cb(struct ble_gap_conn_event *event, void *arg)
+{
+ ble_gap_test_conn_event = *event;
+}
+
+static void
+ble_gap_test_misc_init(void)
+{
+ ble_hs_test_util_init();
+ ble_gap_conn_set_cb(ble_gap_test_misc_connect_cb, NULL);
+}
+
+static void
+ble_gap_test_misc_verify_tx_clear_wl(void)
+{
+ uint8_t param_len;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_hci_tx != NULL);
+
+ ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_CLEAR_WHITE_LIST,
+ ¶m_len);
+ TEST_ASSERT(param_len == 0);
+}
+
+static void
+ble_gap_test_misc_verify_tx_add_wl(struct ble_gap_white_entry *entry)
+{
+ uint8_t param_len;
+ uint8_t *param;
+ int i;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_hci_tx != NULL);
+
+ param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
+ BLE_HCI_OCF_LE_ADD_WHITE_LIST,
+ ¶m_len);
+ TEST_ASSERT(param_len == 7);
+ TEST_ASSERT(param[0] == entry->addr_type);
+ for (i = 0; i < 6; i++) {
+ TEST_ASSERT(param[1 + i] == entry->addr[i]);
+ }
+}
+
+static void
+ble_gap_test_misc_verify_tx_create_conn(void)
+{
+ uint8_t param_len;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_hci_tx != NULL);
+
+ ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_CREATE_CONN,
+ ¶m_len);
+ TEST_ASSERT(param_len == BLE_HCI_CREATE_CONN_LEN);
+}
+
+static void
+ble_gap_test_misc_conn_auto_good_once(struct ble_gap_white_entry *white_list,
+ int white_list_count, int dev_idx)
+{
+ struct hci_le_conn_complete evt;
+ int rc;
+ int i;
+
+ ble_gap_test_misc_init();
+
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ rc = ble_gap_conn_auto_connect(white_list, white_list_count);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_gap_conn_master_in_progress());
+
+ /* Verify tx of clear white list command. */
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_clear_wl();
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST, 0);
+
+ /* Verify tx of add white list commands. */
+ for (i = 0; i < white_list_count; i++) {
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_add_wl(white_list + i);
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_ADD_WHITE_LIST, 0);
+ }
+
+ /* Verify tx of create connection command. */
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_create_conn();
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_CREATE_CONN, 0);
+
+ TEST_ASSERT(ble_gap_conn_master_in_progress());
+ TEST_ASSERT(ble_hs_conn_find(2) == NULL);
+
+ /* Receive connection complete event. */
+ memset(&evt, 0, sizeof evt);
+ evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ memcpy(evt.peer_addr, white_list[dev_idx].addr, 6);
+ rc = ble_gap_conn_rx_conn_complete(&evt);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ TEST_ASSERT(ble_gap_test_conn_event.type ==
+ BLE_GAP_CONN_EVENT_TYPE_CONNECT);
+ TEST_ASSERT(ble_gap_test_conn_event.conn.status == 0);
+ TEST_ASSERT(ble_gap_test_conn_event.conn.handle == 2);
+ TEST_ASSERT(memcmp(ble_gap_test_conn_event.conn.peer_addr,
+ white_list[dev_idx].addr, 6) == 0);
+
+ TEST_ASSERT(ble_hs_conn_find(2) != NULL);
+}
+
+static void
+ble_gap_test_misc_conn_auto_bad_addr(struct ble_gap_white_entry *white_list,
+ int white_list_count)
+{
+ struct hci_le_conn_complete evt;
+ int rc;
+ int i;
+
+ ble_gap_test_misc_init();
+
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ rc = ble_gap_conn_auto_connect(white_list, white_list_count);
+ TEST_ASSERT(rc == 0);
+
+ TEST_ASSERT(ble_gap_conn_master_in_progress());
+
+ /* Verify tx of clear white list command. */
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_clear_wl();
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_CLEAR_WHITE_LIST, 0);
+
+ /* Verify tx of add white list commands. */
+ for (i = 0; i < white_list_count; i++) {
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_add_wl(white_list + i);
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_ADD_WHITE_LIST, 0);
+ }
+
+ /* Verify tx of create connection command. */
+ ble_hci_sched_wakeup();
+ ble_gap_test_misc_verify_tx_create_conn();
+ ble_hs_test_util_rx_le_ack(BLE_HCI_OCF_LE_CREATE_CONN, 0);
+
+ TEST_ASSERT(ble_gap_conn_master_in_progress());
+ TEST_ASSERT(ble_hs_conn_find(2) == NULL);
+
+ /* Receive connection complete event with unknown address. */
+ memset(&evt, 0, sizeof evt);
+ evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+ evt.status = BLE_ERR_SUCCESS;
+ evt.connection_handle = 2;
+ memcpy(evt.peer_addr, ((uint8_t[]){ 1,1,1,1,1,1 }), 6);
+ rc = ble_gap_conn_rx_conn_complete(&evt);
+ TEST_ASSERT(rc != 0);
+
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ TEST_ASSERT(ble_gap_test_conn_event.type ==
+ BLE_GAP_CONN_EVENT_TYPE_CONNECT);
+ TEST_ASSERT(ble_gap_test_conn_event.conn.status == BLE_HS_ECONTROLLER);
+
+ TEST_ASSERT(ble_hs_conn_find(2) == NULL);
+}
+
+TEST_CASE(ble_gap_test_case_conn_auto_good)
+{
+ struct ble_gap_white_entry white_list[] = { {
+ BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 2, 3, 4, 5, 6, 7 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 3, 4, 5, 6, 7, 8 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 4, 5, 6, 7, 8, 9 }
+ } };
+ int white_list_count = sizeof white_list / sizeof white_list[0];
+
+ int i;
+
+ for (i = 0; i < white_list_count; i++) {
+ ble_gap_test_misc_conn_auto_good_once(white_list, white_list_count, i);
+ }
+}
+TEST_CASE(ble_gap_test_case_conn_auto_bad_args)
+{
+ int rc;
+
+ ble_gap_test_misc_init();
+
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ /*** 0 white list entries. */
+ rc = ble_gap_conn_auto_connect(NULL, 0);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ /*** Invalid address type. */
+ rc = ble_gap_conn_auto_connect(
+ ((struct ble_gap_white_entry[]) { {
+ 5, { 1, 2, 3, 4, 5, 6 }
+ }, }), 1);
+ TEST_ASSERT(rc == BLE_HS_EINVAL);
+ TEST_ASSERT(!ble_gap_conn_master_in_progress());
+
+ /*** Connection already in progress. */
+ rc = ble_gap_conn_auto_connect(
+ ((struct ble_gap_white_entry[]) { {
+ BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 }
+ }, }), 1);
+ TEST_ASSERT(rc == 0);
+ TEST_ASSERT(ble_gap_conn_master_in_progress());
+
+ rc = ble_gap_conn_auto_connect(
+ ((struct ble_gap_white_entry[]) { {
+ BLE_ADDR_TYPE_PUBLIC, { 2, 3, 4, 5, 6, 7 }
+ }, }), 1);
+ TEST_ASSERT(rc == BLE_HS_EALREADY);
+}
+
+TEST_CASE(ble_gap_test_case_conn_auto_bad_addr)
+{
+ ble_gap_test_misc_conn_auto_bad_addr(
+ ((struct ble_gap_white_entry[]) { {
+ BLE_ADDR_TYPE_PUBLIC, { 1, 2, 3, 4, 5, 6 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 2, 3, 4, 5, 6, 7 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 3, 4, 5, 6, 7, 8 }
+ }, {
+ BLE_ADDR_TYPE_PUBLIC, { 4, 5, 6, 7, 8, 9 }
+ } }), 4);
+}
+
+TEST_SUITE(ble_gap_suite)
+{
+ ble_gap_test_case_conn_auto_good();
+ ble_gap_test_case_conn_auto_bad_args();
+ ble_gap_test_case_conn_auto_bad_addr();
+}
+
+int
+ble_gap_test_all(void)
+{
+ ble_gap_suite();
+
+ return tu_any_failed;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/test/ble_gatt_read_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gatt_read_test.c b/net/nimble/host/src/test/ble_gatt_read_test.c
index 8c0da37..ec4fe91 100644
--- a/net/nimble/host/src/test/ble_gatt_read_test.c
+++ b/net/nimble/host/src/test/ble_gatt_read_test.c
@@ -679,7 +679,7 @@ TEST_CASE(ble_gatt_read_test_by_handle)
ble_gatt_read_test_misc_verify_good((struct ble_gatt_attr[]) { {
.handle = 0x5432,
.value = (uint8_t[]){ 0xff },
- .value_len = 7
+ .value_len = 1
} });
/* Read a 200-byte attribute. */
@@ -905,14 +905,14 @@ TEST_CASE(ble_gatt_read_test_dsc)
ble_gatt_read_test_misc_dsc_verify_good((struct ble_gatt_attr[]) { {
.handle = 43,
.value = (uint8_t[]){ 1,2,3,4,5,6,7 },
- .value_len = 7
+ .value_len = 7,
} });
/* Read a one-byte attribute. */
ble_gatt_read_test_misc_dsc_verify_good((struct ble_gatt_attr[]) { {
.handle = 0x5432,
.value = (uint8_t[]){ 0xff },
- .value_len = 7
+ .value_len = 1,
} });
/* Read a 200-byte attribute. */
@@ -927,7 +927,7 @@ TEST_CASE(ble_gatt_read_test_dsc)
(struct ble_gatt_attr[]) { {
.handle = 719,
.value = (uint8_t[]){ 1,2,3,4,5,6,7 },
- .value_len = 7
+ .value_len = 7,
} });
/* Fail due to invalid PDU. */
@@ -935,7 +935,7 @@ TEST_CASE(ble_gatt_read_test_dsc)
(struct ble_gatt_attr[]) { {
.handle = 65,
.value = (uint8_t[]){ 0xfa, 0x4c },
- .value_len = 2
+ .value_len = 2,
} });
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/test/ble_hs_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test.c b/net/nimble/host/src/test/ble_hs_test.c
index d959f11..0b599cc 100644
--- a/net/nimble/host/src/test/ble_hs_test.c
+++ b/net/nimble/host/src/test/ble_hs_test.c
@@ -66,6 +66,7 @@ main(void)
ble_gatts_reg_test_all();
ble_gatts_notify_test_all();
ble_gatt_find_s_test_all();
+ ble_gap_test_all();
return tu_any_failed;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/test/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index ff7963e..f3c7359 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -80,6 +80,7 @@ ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr)
evt.connection_handle = handle;
memcpy(evt.peer_addr, addr, 6);
rc = ble_gap_conn_rx_conn_complete(&evt);
+ TEST_ASSERT(rc == 0);
conn = ble_hs_conn_find(handle);
TEST_ASSERT_FATAL(conn != NULL);
@@ -328,6 +329,25 @@ ble_hs_test_util_rx_dir_adv_acks(void)
TEST_ASSERT(ble_gap_conn_slave_in_progress());
}
+uint8_t *
+ble_hs_test_util_verify_tx_hci(uint8_t ogf, uint16_t ocf,
+ uint8_t *out_param_len)
+{
+ uint16_t opcode;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_hci_tx != NULL);
+
+ opcode = le16toh(ble_hs_test_util_prev_hci_tx);
+ TEST_ASSERT(BLE_HCI_OGF(opcode) == ogf);
+ TEST_ASSERT(BLE_HCI_OCF(opcode) == ocf);
+
+ if (out_param_len != NULL) {
+ *out_param_len = ble_hs_test_util_prev_hci_tx[2];
+ }
+
+ return ble_hs_test_util_prev_hci_tx + 3;
+}
+
void
ble_hs_test_util_tx_all(void)
{
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/ca671d23/net/nimble/host/src/test/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.h b/net/nimble/host/src/test/ble_hs_test_util.h
index 2adcc60..c748923 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -55,6 +55,8 @@ void ble_hs_test_util_rx_num_completed_pkts_event(
void ble_hs_test_util_rx_und_adv_acks(void);
void ble_hs_test_util_rx_und_adv_acks_count(int count);
void ble_hs_test_util_rx_dir_adv_acks(void);
+uint8_t *ble_hs_test_util_verify_tx_hci(uint8_t ogf, uint16_t ocf,
+ uint8_t *out_param_len);
void ble_hs_test_util_tx_all(void);
void ble_hs_test_util_init(void);