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/30 00:56:18 UTC
[1/3] incubator-mynewt-larva git commit: L2CAP signal channel.
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master ccda6d4b1 -> c6d01fdad
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/test/ble_l2cap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_l2cap_test.c b/net/nimble/host/src/test/ble_l2cap_test.c
index fd6be31..52aa836 100644
--- a/net/nimble/host/src/test/ble_l2cap_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_test.c
@@ -21,6 +21,7 @@
#include "host/host_hci.h"
#include "host/ble_hs_test.h"
#include "ble_hs_conn.h"
+#include "ble_gap_priv.h"
#include "ble_hci_sched.h"
#include "ble_hs_test_util.h"
#include "ble_l2cap_priv.h"
@@ -28,6 +29,13 @@
#define BLE_L2CAP_TEST_CID 99
+static int ble_l2cap_test_update_status;
+static void *ble_l2cap_test_update_arg;
+
+/*****************************************************************************
+ * $util *
+ *****************************************************************************/
+
#define BLE_L2CAP_TEST_UTIL_HCI_HDR(handle, pb, len) \
((struct hci_data_hdr) { \
.hdh_handle_pb_bc = ((handle) << 0) | \
@@ -35,20 +43,192 @@
.hdh_len = (len) \
})
+static void
+ble_l2cap_test_util_init(void)
+{
+ ble_hs_test_util_init();
+ ble_l2cap_test_update_status = -1;
+ ble_l2cap_test_update_arg = (void *)(uintptr_t)-1;
+}
+
+static void
+ble_l2cap_test_util_rx_update_req(struct ble_hs_conn *conn, uint8_t id,
+ struct ble_l2cap_sig_update_params *params)
+{
+ struct ble_l2cap_sig_update_req req;
+ struct ble_l2cap_sig_hdr sig_hdr;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int rc;
+
+ hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+
+ om = ble_att_get_pkthdr();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ om = ble_l2cap_prepend_hdr(om, BLE_L2CAP_CID_SIG,
+ BLE_L2CAP_SIG_HDR_SZ +
+ BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ sig_hdr.op = BLE_L2CAP_SIG_OP_UPDATE_REQ;
+ sig_hdr.identifier = id;
+ sig_hdr.length = BLE_L2CAP_SIG_UPDATE_REQ_SZ;
+ req.itvl_min = params->itvl_min;
+ req.itvl_max = params->itvl_max;
+ req.slave_latency = params->slave_latency;
+ req.timeout_multiplier = params->timeout_multiplier;
+
+ v = os_mbuf_extend(om, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ rc = ble_l2cap_sig_update_req_write(
+ v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ, &sig_hdr, &req);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_l2cap_rx(conn, &hci_hdr, om);
+ TEST_ASSERT_FATAL(rc == 0);
+}
+
static int
-ble_l2cap_test_util_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- struct os_mbuf **om)
+ble_l2cap_test_util_rx_update_rsp(struct ble_hs_conn *conn,
+ uint8_t id, uint16_t result)
+{
+ struct ble_l2cap_sig_update_rsp rsp;
+ struct ble_l2cap_sig_hdr sig_hdr;
+ struct hci_data_hdr hci_hdr;
+ struct os_mbuf *om;
+ void *v;
+ int rc;
+
+ hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(
+ 2, BLE_HCI_PB_FIRST_FLUSH,
+ BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+
+ om = ble_att_get_pkthdr();
+ TEST_ASSERT_FATAL(om != NULL);
+
+ om = ble_l2cap_prepend_hdr(om, BLE_L2CAP_CID_SIG,
+ BLE_L2CAP_SIG_HDR_SZ +
+ BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ TEST_ASSERT_FATAL(om != NULL);
+
+ sig_hdr.op = BLE_L2CAP_SIG_OP_UPDATE_RSP;
+ sig_hdr.identifier = id;
+ sig_hdr.length = BLE_L2CAP_SIG_UPDATE_RSP_SZ;
+ rsp.result = result;
+
+ v = os_mbuf_extend(om, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ TEST_ASSERT_FATAL(v != NULL);
+
+ rc = ble_l2cap_sig_update_rsp_write(
+ v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ, &sig_hdr, &rsp);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ rc = ble_l2cap_rx(conn, &hci_hdr, om);
+ return rc;
+}
+
+/**
+ * @return The L2CAP sig identifier in the request.
+ */
+static uint8_t
+ble_l2cap_test_util_verify_tx_update_req(
+ struct ble_l2cap_sig_update_params *params)
+{
+ struct ble_l2cap_sig_update_req req;
+ struct ble_l2cap_sig_hdr hdr;
+ int rc;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);
+ TEST_ASSERT(OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx) ==
+ BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ rc = ble_l2cap_sig_hdr_parse(ble_hs_test_util_prev_tx->om_data,
+ ble_hs_test_util_prev_tx->om_len, &hdr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_prev_tx->om_data += BLE_L2CAP_SIG_HDR_SZ;
+ ble_hs_test_util_prev_tx->om_len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ rc = ble_l2cap_sig_update_req_parse(ble_hs_test_util_prev_tx->om_data,
+ ble_hs_test_util_prev_tx->om_len,
+ &req);
+ TEST_ASSERT(hdr.op == BLE_L2CAP_SIG_OP_UPDATE_REQ);
+ TEST_ASSERT(hdr.length == BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ TEST_ASSERT(req.itvl_min == params->itvl_min);
+ TEST_ASSERT(req.itvl_max == params->itvl_max);
+ TEST_ASSERT(req.slave_latency == params->slave_latency);
+ TEST_ASSERT(req.timeout_multiplier == params->timeout_multiplier);
+
+ return hdr.identifier;
+}
+
+static void
+ble_l2cap_test_util_verify_tx_update_rsp(uint8_t exp_id, uint16_t exp_result)
+{
+ struct ble_l2cap_sig_update_rsp rsp;
+ struct ble_l2cap_sig_hdr hdr;
+ int rc;
+
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);
+ TEST_ASSERT(OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx) ==
+ BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ rc = ble_l2cap_sig_hdr_parse(ble_hs_test_util_prev_tx->om_data,
+ ble_hs_test_util_prev_tx->om_len, &hdr);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_prev_tx->om_data += BLE_L2CAP_SIG_HDR_SZ;
+ ble_hs_test_util_prev_tx->om_len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ rc = ble_l2cap_sig_update_rsp_parse(ble_hs_test_util_prev_tx->om_data,
+ ble_hs_test_util_prev_tx->om_len,
+ &rsp);
+ TEST_ASSERT(hdr.op == BLE_L2CAP_SIG_OP_UPDATE_RSP);
+ TEST_ASSERT(hdr.identifier == exp_id);
+ TEST_ASSERT(hdr.length == BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ TEST_ASSERT(rsp.result == exp_result);
+}
+
+static void
+ble_l2cap_test_util_verify_tx_update_conn(
+ struct ble_gap_conn_upd_params *params)
+{
+ uint8_t param_len;
+ uint8_t *param;
+
+ 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_CONN_UPDATE,
+ ¶m_len);
+ TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN);
+ TEST_ASSERT(le16toh(param + 0) == 2);
+ TEST_ASSERT(le16toh(param + 2) == params->itvl_min);
+ TEST_ASSERT(le16toh(param + 4) == params->itvl_max);
+ TEST_ASSERT(le16toh(param + 6) == params->latency);
+ TEST_ASSERT(le16toh(param + 8) == params->supervision_timeout);
+ TEST_ASSERT(le16toh(param + 10) == params->min_ce_len);
+ TEST_ASSERT(le16toh(param + 12) == params->max_ce_len);
+}
+
+static int
+ble_l2cap_test_util_dummy_rx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan, struct os_mbuf **om)
{
return 0;
}
static struct ble_hs_conn *
-ble_l2cap_test_create_conn(uint16_t handle, uint8_t *addr)
+ble_l2cap_test_util_create_conn(uint16_t handle, uint8_t *addr,
+ ble_gap_conn_fn *cb, void *cb_arg)
{
struct ble_l2cap_chan *chan;
struct ble_hs_conn *conn;
- conn = ble_hs_test_util_create_conn(handle, addr, NULL, NULL);
+ conn = ble_hs_test_util_create_conn(handle, addr, cb, cb_arg);
chan = ble_l2cap_chan_alloc();
TEST_ASSERT_FATAL(chan != NULL);
@@ -56,7 +236,7 @@ ble_l2cap_test_create_conn(uint16_t handle, uint8_t *addr)
chan->blc_cid = BLE_L2CAP_TEST_CID;
chan->blc_my_mtu = 240;
chan->blc_default_mtu = 240;
- chan->blc_rx_fn = ble_l2cap_test_util_rx;
+ chan->blc_rx_fn = ble_l2cap_test_util_dummy_rx;
ble_hs_conn_chan_insert(conn, chan);
@@ -64,9 +244,9 @@ ble_l2cap_test_create_conn(uint16_t handle, uint8_t *addr)
}
static int
-ble_l2cap_test_rx_first_frag(struct ble_hs_conn *conn,
- uint16_t l2cap_frag_len,
- uint16_t cid, uint16_t l2cap_len)
+ble_l2cap_test_util_rx_first_frag(struct ble_hs_conn *conn,
+ uint16_t l2cap_frag_len,
+ uint16_t cid, uint16_t l2cap_len)
{
struct hci_data_hdr hci_hdr;
struct os_mbuf *om;
@@ -91,7 +271,7 @@ ble_l2cap_test_rx_first_frag(struct ble_hs_conn *conn,
}
static int
-ble_l2cap_test_rx_next_frag(struct ble_hs_conn *conn, uint16_t hci_len)
+ble_l2cap_test_util_rx_next_frag(struct ble_hs_conn *conn, uint16_t hci_len)
{
struct hci_data_hdr hci_hdr;
struct os_mbuf *om;
@@ -111,53 +291,64 @@ ble_l2cap_test_rx_next_frag(struct ble_hs_conn *conn, uint16_t hci_len)
}
static void
-ble_l2cap_test_verify_first_frag(struct ble_hs_conn *conn,
- uint16_t l2cap_frag_len,
- uint16_t l2cap_len)
+ble_l2cap_test_util_verify_first_frag(struct ble_hs_conn *conn,
+ uint16_t l2cap_frag_len,
+ uint16_t l2cap_len)
{
int rc;
- rc = ble_l2cap_test_rx_first_frag(conn, l2cap_frag_len,
- BLE_L2CAP_TEST_CID, l2cap_len);
+ rc = ble_l2cap_test_util_rx_first_frag(conn, l2cap_frag_len,
+ BLE_L2CAP_TEST_CID, l2cap_len);
TEST_ASSERT(rc == 0);
TEST_ASSERT(conn->bhc_rx_chan != NULL &&
conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID);
}
static void
-ble_l2cap_test_verify_middle_frag(struct ble_hs_conn *conn, uint16_t hci_len)
+ble_l2cap_test_util_verify_middle_frag(struct ble_hs_conn *conn,
+ uint16_t hci_len)
{
int rc;
- rc = ble_l2cap_test_rx_next_frag(conn, hci_len);
+ rc = ble_l2cap_test_util_rx_next_frag(conn, hci_len);
TEST_ASSERT(rc == 0);
TEST_ASSERT(conn->bhc_rx_chan != NULL &&
conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID);
}
static void
-ble_l2cap_test_verify_last_frag(struct ble_hs_conn *conn, uint16_t hci_len)
+ble_l2cap_test_util_verify_last_frag(struct ble_hs_conn *conn,
+ uint16_t hci_len)
{
int rc;
- rc = ble_l2cap_test_rx_next_frag(conn, hci_len);
+ rc = ble_l2cap_test_util_rx_next_frag(conn, hci_len);
TEST_ASSERT(rc == 0);
TEST_ASSERT(conn->bhc_rx_chan == NULL);
}
+/*****************************************************************************
+ * $rx *
+ *****************************************************************************/
+
TEST_CASE(ble_l2cap_test_case_bad_header)
{
struct ble_hs_conn *conn;
int rc;
- ble_hs_test_util_init();
+ ble_l2cap_test_util_init();
- conn = ble_l2cap_test_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}));
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
- rc = ble_l2cap_test_rx_first_frag(conn, 14, 1234, 10);
+ rc = ble_l2cap_test_util_rx_first_frag(conn, 14, 1234, 10);
TEST_ASSERT(rc == BLE_HS_ENOENT);
}
+/*****************************************************************************
+ * $fragmentation *
+ *****************************************************************************/
+
TEST_CASE(ble_l2cap_test_case_frag_single)
{
struct hci_data_hdr hci_hdr;
@@ -165,9 +356,10 @@ TEST_CASE(ble_l2cap_test_case_frag_single)
struct os_mbuf *om;
int rc;
- ble_hs_test_util_init();
+ ble_l2cap_test_util_init();
- conn = ble_l2cap_test_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}));
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
/*** HCI header specifies middle fragment without start. */
hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
@@ -182,37 +374,40 @@ TEST_CASE(ble_l2cap_test_case_frag_single)
TEST_ASSERT(rc == BLE_HS_EBADDATA);
/*** Packet consisting of three fragments. */
- ble_l2cap_test_verify_first_frag(conn, 10, 30);
- ble_l2cap_test_verify_middle_frag(conn, 10);
- ble_l2cap_test_verify_last_frag(conn, 10);
+ ble_l2cap_test_util_verify_first_frag(conn, 10, 30);
+ ble_l2cap_test_util_verify_middle_frag(conn, 10);
+ ble_l2cap_test_util_verify_last_frag(conn, 10);
/*** Packet consisting of five fragments. */
- ble_l2cap_test_verify_first_frag(conn, 8, 49);
- ble_l2cap_test_verify_middle_frag(conn, 13);
- ble_l2cap_test_verify_middle_frag(conn, 2);
- ble_l2cap_test_verify_middle_frag(conn, 21);
- ble_l2cap_test_verify_last_frag(conn, 5);
+ ble_l2cap_test_util_verify_first_frag(conn, 8, 49);
+ ble_l2cap_test_util_verify_middle_frag(conn, 13);
+ ble_l2cap_test_util_verify_middle_frag(conn, 2);
+ ble_l2cap_test_util_verify_middle_frag(conn, 21);
+ ble_l2cap_test_util_verify_last_frag(conn, 5);
}
TEST_CASE(ble_l2cap_test_case_frag_multiple)
{
struct ble_hs_conn *conns[3];
- ble_hs_test_util_init();
-
- conns[0] = ble_l2cap_test_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}));
- conns[1] = ble_l2cap_test_create_conn(3, ((uint8_t[]){2,3,4,5,6,7}));
- conns[2] = ble_l2cap_test_create_conn(4, ((uint8_t[]){3,4,5,6,7,8}));
-
- ble_l2cap_test_verify_first_frag(conns[0], 3, 10);
- ble_l2cap_test_verify_first_frag(conns[1], 2, 5);
- ble_l2cap_test_verify_middle_frag(conns[0], 6);
- ble_l2cap_test_verify_first_frag(conns[2], 1, 4);
- ble_l2cap_test_verify_middle_frag(conns[1], 2);
- ble_l2cap_test_verify_last_frag(conns[1], 1);
- ble_l2cap_test_verify_middle_frag(conns[2], 2);
- ble_l2cap_test_verify_last_frag(conns[2], 1);
- ble_l2cap_test_verify_last_frag(conns[0], 1);
+ ble_l2cap_test_util_init();
+
+ conns[0] = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+ conns[1] = ble_l2cap_test_util_create_conn(3, ((uint8_t[]){2,3,4,5,6,7}),
+ NULL, NULL);
+ conns[2] = ble_l2cap_test_util_create_conn(4, ((uint8_t[]){3,4,5,6,7,8}),
+ NULL, NULL);
+
+ ble_l2cap_test_util_verify_first_frag(conns[0], 3, 10);
+ ble_l2cap_test_util_verify_first_frag(conns[1], 2, 5);
+ ble_l2cap_test_util_verify_middle_frag(conns[0], 6);
+ ble_l2cap_test_util_verify_first_frag(conns[2], 1, 4);
+ ble_l2cap_test_util_verify_middle_frag(conns[1], 2);
+ ble_l2cap_test_util_verify_last_frag(conns[1], 1);
+ ble_l2cap_test_util_verify_middle_frag(conns[2], 2);
+ ble_l2cap_test_util_verify_last_frag(conns[2], 1);
+ ble_l2cap_test_util_verify_last_frag(conns[0], 1);
}
TEST_CASE(ble_l2cap_test_case_frag_channels)
@@ -220,12 +415,13 @@ TEST_CASE(ble_l2cap_test_case_frag_channels)
struct ble_hs_conn *conn;
int rc;
- ble_hs_test_util_init();
+ ble_l2cap_test_util_init();
- conn = ble_l2cap_test_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}));
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
/* Receive a starting fragment on the first channel. */
- rc = ble_l2cap_test_rx_first_frag(conn, 14, BLE_L2CAP_TEST_CID, 30);
+ rc = ble_l2cap_test_util_rx_first_frag(conn, 14, BLE_L2CAP_TEST_CID, 30);
TEST_ASSERT(rc == 0);
TEST_ASSERT(conn->bhc_rx_chan != NULL &&
conn->bhc_rx_chan->blc_cid == BLE_L2CAP_TEST_CID);
@@ -233,95 +429,232 @@ TEST_CASE(ble_l2cap_test_case_frag_channels)
/* Receive a starting fragment on a different channel. The first fragment
* should get discarded.
*/
- rc = ble_l2cap_test_rx_first_frag(conn, 14, BLE_L2CAP_CID_ATT, 30);
+ rc = ble_l2cap_test_util_rx_first_frag(conn, 14, BLE_L2CAP_CID_ATT, 30);
TEST_ASSERT(rc == 0);
TEST_ASSERT(conn->bhc_rx_chan != NULL &&
conn->bhc_rx_chan->blc_cid == BLE_L2CAP_CID_ATT);
}
-static void
-ble_l2cap_test_util_verify_tx_update_conn(
- struct ble_gap_conn_upd_params *params)
+/*****************************************************************************
+ * $unsolicited response *
+ *****************************************************************************/
+
+TEST_CASE(ble_l2cap_test_case_sig_unsol_rsp)
{
- uint8_t param_len;
- uint8_t *param;
+ struct ble_hs_conn *conn;
+ int rc;
- TEST_ASSERT_FATAL(ble_hs_test_util_prev_hci_tx != NULL);
+ ble_l2cap_test_util_init();
- param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LE,
- BLE_HCI_OCF_LE_CONN_UPDATE,
- ¶m_len);
- TEST_ASSERT(param_len == BLE_HCI_CONN_UPDATE_LEN);
- TEST_ASSERT(le16toh(param + 0) == 2);
- TEST_ASSERT(le16toh(param + 2) == params->itvl_min);
- TEST_ASSERT(le16toh(param + 4) == params->itvl_max);
- TEST_ASSERT(le16toh(param + 6) == params->latency);
- TEST_ASSERT(le16toh(param + 8) == params->supervision_timeout);
- TEST_ASSERT(le16toh(param + 10) == params->min_ce_len);
- TEST_ASSERT(le16toh(param + 12) == params->max_ce_len);
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ NULL, NULL);
+
+ /* Receive an unsolicited response. */
+ rc = ble_l2cap_test_util_rx_update_rsp(conn, 100, 0);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Ensure we did not send anything in return. */
+ ble_hs_test_util_tx_all();
+ TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx == NULL);
}
-TEST_CASE(ble_l2cap_test_case_sig_update)
+/*****************************************************************************
+ * $update *
+ *****************************************************************************/
+
+static int
+ble_l2cap_test_util_conn_cb(int event, int status,
+ struct ble_gap_conn_ctxt *ctxt, void *arg)
{
+ int *accept;
+
+ switch (event) {
+ case BLE_GAP_EVENT_L2CAP_UPDATE_REQ:
+ accept = arg;
+ return !*accept;
+
+ default:
+ return 0;
+ }
+}
+
+static void
+ble_l2cap_test_util_peer_updates(int accept)
+{
+ struct ble_l2cap_sig_update_params l2cap_params;
struct ble_gap_conn_upd_params params;
struct ble_hs_conn *conn;
- struct hci_data_hdr hci_hdr;
- struct os_mbuf *om;
- int rc;
- ble_hs_test_util_init();
+ ble_l2cap_test_util_init();
- conn = ble_l2cap_test_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}));
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, &accept);
- uint8_t pkt[] = {
- BLE_L2CAP_SIG_OP_UPDATE_REQ, /* Op. */
- 1, /* Identifier. */
- 0x08, 0x00, /* Length (8). */
- 0x00, 0x02, /* Interval min (0x200). */
- 0x00, 0x03, /* Interval max (0x300). */
- 0x00, 0x00, /* Slave latency (0). */
- 0x00, 0x01, /* Timeout multiplier (0x100). */
- };
+ l2cap_params.itvl_min = 0x200;
+ l2cap_params.itvl_max = 0x300;
+ l2cap_params.slave_latency = 0;
+ l2cap_params.timeout_multiplier = 0x100;
+ ble_l2cap_test_util_rx_update_req(conn, 1, &l2cap_params);
- hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(
- 2, BLE_HCI_PB_FIRST_FLUSH,
- BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + sizeof pkt);
+ /* Ensure an update response command got sent. */
+ ble_hs_process_tx_data_queue();
+ ble_l2cap_test_util_verify_tx_update_rsp(1, !accept);
+
+ if (accept) {
+ /* Ensure update request gets sent. */
+ ble_gattc_wakeup();
+ ble_hci_sched_wakeup();
+
+ params.itvl_min = 0x200;
+ params.itvl_max = 0x300;
+ params.latency = 0;
+ params.supervision_timeout = 0x100;
+ params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
+ params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
+ ble_l2cap_test_util_verify_tx_update_conn(¶ms);
+ } else {
+ /* Ensure no update got scheduled. */
+ TEST_ASSERT(!ble_gap_conn_update_in_progress(BLE_HS_CONN_HANDLE_NONE));
+ }
+}
- om = ble_att_get_pkthdr();
- TEST_ASSERT_FATAL(om != NULL);
+static void
+ble_l2cap_test_util_update_cb(int status, void *arg)
+{
+ ble_l2cap_test_update_status = status;
+ ble_l2cap_test_update_arg = arg;
+}
- om = ble_l2cap_prepend_hdr(om, BLE_L2CAP_CID_SIG, sizeof pkt);
- TEST_ASSERT_FATAL(om != NULL);
+static void
+ble_l2cap_test_util_we_update(int peer_accepts)
+{
+ struct ble_l2cap_sig_update_params params;
+ struct ble_hs_conn *conn;
+ uint8_t id;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ /* Only the slave can initiate the L2CAP connection update procedure. */
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
- rc = os_mbuf_append(om, pkt, sizeof pkt);
+ params.itvl_min = 0x200;
+ params.itvl_min = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(conn->bhc_handle, ¶ms,
+ ble_l2cap_test_util_update_cb, NULL);
TEST_ASSERT_FATAL(rc == 0);
- rc = ble_l2cap_rx(conn, &hci_hdr, om);
+ ble_hs_test_util_tx_all();
+
+ /* Ensure an update request got sent. */
+ id = ble_l2cap_test_util_verify_tx_update_req(¶ms);
+
+ /* Receive response from peer. */
+ rc = ble_l2cap_test_util_rx_update_rsp(conn, id, !peer_accepts);
+ TEST_ASSERT(rc == 0);
+
+ /* Ensure callback got called. */
+ if (peer_accepts) {
+ TEST_ASSERT(ble_l2cap_test_update_status == 0);
+ } else {
+ TEST_ASSERT(ble_l2cap_test_update_status == BLE_HS_EREJECT);
+ }
+ TEST_ASSERT(ble_l2cap_test_update_arg == NULL);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_accept)
+{
+ ble_l2cap_test_util_peer_updates(1);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_reject)
+{
+ ble_l2cap_test_util_peer_updates(0);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_init_accept)
+{
+ ble_l2cap_test_util_we_update(1);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_init_reject)
+{
+ ble_l2cap_test_util_we_update(0);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_master)
+{
+ struct ble_l2cap_sig_update_params params;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ ble_l2cap_test_util_init();
+
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ params.itvl_min = 0x200;
+ params.itvl_min = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(conn->bhc_handle, ¶ms,
+ ble_l2cap_test_util_update_cb, NULL);
TEST_ASSERT_FATAL(rc == 0);
- /* Ensure an update response command got sent. */
- ble_hs_process_tx_data_queue();
- TEST_ASSERT_FATAL(ble_hs_test_util_prev_tx != NULL);
- TEST_ASSERT(OS_MBUF_PKTLEN(ble_hs_test_util_prev_tx) ==
- BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
- TEST_ASSERT(ble_hs_test_util_prev_tx->om_data[0] ==
- BLE_L2CAP_SIG_OP_UPDATE_RSP);
- TEST_ASSERT(ble_hs_test_util_prev_tx->om_data[1] == 1);
- TEST_ASSERT(le16toh(ble_hs_test_util_prev_tx->om_data + 2) == 2);
- TEST_ASSERT(le16toh(ble_hs_test_util_prev_tx->om_data + 4) == 0);
+ ble_hs_test_util_tx_all();
+
+ /* Ensure callback indicates failure. */
+ TEST_ASSERT(ble_l2cap_test_update_status == BLE_HS_EINVAL);
+ TEST_ASSERT(ble_l2cap_test_update_arg == NULL);
+}
+
+TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_bad_id)
+{
+ struct ble_l2cap_sig_update_params params;
+ struct ble_hs_conn *conn;
+ uint8_t id;
+ int rc;
+
+ ble_l2cap_test_util_init();
- /* Ensure update request gets sent. */
- ble_gattc_wakeup();
- ble_hci_sched_wakeup();
+ conn = ble_l2cap_test_util_create_conn(2, ((uint8_t[]){1,2,3,4,5,6}),
+ ble_l2cap_test_util_conn_cb, NULL);
+
+ /* Only the slave can initiate the L2CAP connection update procedure. */
+ conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
params.itvl_min = 0x200;
- params.itvl_max = 0x300;
- params.latency = 0;
- params.supervision_timeout = 0x100;
- params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
- params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
+ params.itvl_min = 0x300;
+ params.slave_latency = 0;
+ params.timeout_multiplier = 0x100;
+ rc = ble_l2cap_sig_update(conn->bhc_handle, ¶ms,
+ ble_l2cap_test_util_update_cb, NULL);
+ TEST_ASSERT_FATAL(rc == 0);
+
+ ble_hs_test_util_tx_all();
+
+ /* Ensure an update request got sent. */
+ id = ble_l2cap_test_util_verify_tx_update_req(¶ms);
+
+ /* Receive response from peer with incorrect ID. */
+ rc = ble_l2cap_test_util_rx_update_rsp(conn, id + 1, 0);
+ TEST_ASSERT(rc == BLE_HS_ENOENT);
+
+ /* Ensure callback did not get called. */
+ TEST_ASSERT(ble_l2cap_test_update_status == -1);
+
+ /* Receive response from peer with correct ID. */
+ rc = ble_l2cap_test_util_rx_update_rsp(conn, id, 0);
+ TEST_ASSERT(rc == 0);
- ble_l2cap_test_util_verify_tx_update_conn(¶ms);
+ /* Ensure callback got called. */
+ TEST_ASSERT(ble_l2cap_test_update_status == 0);
+ TEST_ASSERT(ble_l2cap_test_update_arg == NULL);
}
TEST_SUITE(ble_l2cap_test_suite)
@@ -330,7 +663,13 @@ TEST_SUITE(ble_l2cap_test_suite)
ble_l2cap_test_case_frag_single();
ble_l2cap_test_case_frag_multiple();
ble_l2cap_test_case_frag_channels();
- ble_l2cap_test_case_sig_update();
+ ble_l2cap_test_case_sig_unsol_rsp();
+ ble_l2cap_test_case_sig_update_accept();
+ ble_l2cap_test_case_sig_update_reject();
+ ble_l2cap_test_case_sig_update_init_accept();
+ ble_l2cap_test_case_sig_update_init_reject();
+ ble_l2cap_test_case_sig_update_init_fail_master();
+ ble_l2cap_test_case_sig_update_init_fail_bad_id();
}
int
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/project/bleshell/src/bleshell_priv.h
----------------------------------------------------------------------
diff --git a/project/bleshell/src/bleshell_priv.h b/project/bleshell/src/bleshell_priv.h
index b6534ac..9bca5b7 100644
--- a/project/bleshell/src/bleshell_priv.h
+++ b/project/bleshell/src/bleshell_priv.h
@@ -10,6 +10,8 @@ struct ble_hs_adv_fields;
struct ble_gap_conn_upd_params;
struct ble_gap_conn_crt_params;
struct hci_adv_params;
+struct ble_l2cap_sig_update_req;
+struct ble_l2cap_sig_update_params;
#define BLESHELL_MAX_CONNS 8
@@ -68,7 +70,8 @@ uint8_t bleshell_gatt_service_changed[4];
void bleshell_printf(const char *fmt, ...);
void print_addr(void *addr);
void print_uuid(void *uuid128);
-struct cmd_entry *parse_cmd_find(struct cmd_entry *cmds, char *name);
+const struct cmd_entry *parse_cmd_find(const struct cmd_entry *cmds,
+ char *name);
struct kv_pair *parse_kv_find(struct kv_pair *kvs, char *name);
char *parse_arg_find(char *key);
long parse_arg_long_bounds(char *name, long min, long max, int *out_status);
@@ -127,5 +130,7 @@ int bleshell_set_adv_data(struct ble_hs_adv_fields *adv_fields);
int bleshell_update_conn(uint16_t conn_handle,
struct ble_gap_conn_upd_params *params);
void bleshell_chrup(uint16_t attr_handle);
+int bleshell_l2cap_update(uint16_t conn_handle,
+ struct ble_l2cap_sig_update_params *params);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/project/bleshell/src/cmd.c
----------------------------------------------------------------------
diff --git a/project/bleshell/src/cmd.c b/project/bleshell/src/cmd.c
index 880b319..589e367 100644
--- a/project/bleshell/src/cmd.c
+++ b/project/bleshell/src/cmd.c
@@ -8,6 +8,7 @@
#include "nimble/hci_common.h"
#include "host/ble_gap.h"
#include "host/ble_hs_adv.h"
+#include "../src/ble_l2cap_priv.h"
#include "bleshell_priv.h"
@@ -22,9 +23,9 @@ static bssnz_t uint8_t cmd_buf[CMD_BUF_SZ];
*****************************************************************************/
static int
-cmd_exec(struct cmd_entry *cmds, int argc, char **argv)
+cmd_exec(const struct cmd_entry *cmds, int argc, char **argv)
{
- struct cmd_entry *cmd;
+ const struct cmd_entry *cmd;
int rc;
if (argc <= 1) {
@@ -468,7 +469,7 @@ cmd_find_inc_svcs(int argc, char **argv)
return 0;
}
-static struct cmd_entry cmd_find_entries[] = {
+static const struct cmd_entry cmd_find_entries[] = {
{ "inc_svcs", cmd_find_inc_svcs },
{ NULL, NULL }
};
@@ -487,6 +488,71 @@ cmd_find(int argc, char **argv)
}
/*****************************************************************************
+ * $l2cap *
+ *****************************************************************************/
+
+static int
+cmd_l2cap_update(int argc, char **argv)
+{
+ struct ble_l2cap_sig_update_params params;
+ uint16_t conn_handle;
+ int rc;
+
+ conn_handle = parse_arg_uint16("conn", &rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ params.itvl_min = parse_arg_uint16_dflt(
+ "itvl_min", BLE_GAP_INITIAL_CONN_ITVL_MIN, &rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ params.itvl_max = parse_arg_uint16_dflt(
+ "itvl_max", BLE_GAP_INITIAL_CONN_ITVL_MAX, &rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ params.slave_latency = parse_arg_uint16_dflt("latency", 0, &rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ params.timeout_multiplier = parse_arg_uint16_dflt("timeout", 0x0100, &rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = bleshell_l2cap_update(conn_handle, ¶ms);
+ if (rc != 0) {
+ bleshell_printf("error txing l2cap update; rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static const struct cmd_entry cmd_l2cap_entries[] = {
+ { "update", cmd_l2cap_update },
+ { NULL, NULL }
+};
+
+static int
+cmd_l2cap(int argc, char **argv)
+{
+ int rc;
+
+ rc = cmd_exec(cmd_l2cap_entries, argc, argv);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************
* $mtu *
*****************************************************************************/
@@ -1321,6 +1387,7 @@ static struct cmd_entry cmd_b_entries[] = {
{ "chrup", cmd_chrup },
{ "disc", cmd_disc },
{ "find", cmd_find },
+ { "l2cap", cmd_l2cap },
{ "mtu", cmd_mtu },
{ "read", cmd_read },
{ "scan", cmd_scan },
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/project/bleshell/src/main.c
----------------------------------------------------------------------
diff --git a/project/bleshell/src/main.c b/project/bleshell/src/main.c
index 55abafa..221b496 100755
--- a/project/bleshell/src/main.c
+++ b/project/bleshell/src/main.c
@@ -36,6 +36,7 @@
#include "host/ble_gap.h"
#include "host/ble_gatt.h"
#include "controller/ble_ll.h"
+#include "../src/ble_hs_conn.h"
#define BSWAP16(x) ((uint16_t)(((x) << 8) | (((x) & 0xff00) >> 8)))
@@ -877,6 +878,12 @@ bleshell_on_connect(int event, int status, struct ble_gap_conn_ctxt *ctxt,
}
static void
+bleshell_on_l2cap_update(int status, void *arg)
+{
+ bleshell_printf("l2cap update complete; status=%d\n", status);
+}
+
+static void
bleshell_on_wl_set(int status, void *arg)
{
bleshell_printf("white list set status=%d\n", status);
@@ -1172,6 +1179,17 @@ bleshell_chrup(uint16_t attr_handle)
ble_gatts_chr_updated(attr_handle);
}
+int
+bleshell_l2cap_update(uint16_t conn_handle,
+ struct ble_l2cap_sig_update_params *params)
+{
+ int rc;
+
+ rc = ble_l2cap_sig_update(conn_handle, params, bleshell_on_l2cap_update,
+ NULL);
+ return rc;
+}
+
/**
* BLE test task
*
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/project/bleshell/src/parse.c
----------------------------------------------------------------------
diff --git a/project/bleshell/src/parse.c b/project/bleshell/src/parse.c
index 561f5a2..4c94492 100644
--- a/project/bleshell/src/parse.c
+++ b/project/bleshell/src/parse.c
@@ -66,10 +66,10 @@ parse_err_too_few_args(char *cmd_name)
return -1;
}
-struct cmd_entry *
-parse_cmd_find(struct cmd_entry *cmds, char *name)
+const struct cmd_entry *
+parse_cmd_find(const struct cmd_entry *cmds, char *name)
{
- struct cmd_entry *cmd;
+ const struct cmd_entry *cmd;
int i;
for (i = 0; cmds[i].name != NULL; i++) {
[2/3] incubator-mynewt-larva git commit: L2CAP signal channel.
Posted by cc...@apache.org.
L2CAP signal channel.
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/894a15c3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/894a15c3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/894a15c3
Branch: refs/heads/master
Commit: 894a15c30ddb9a37275056c09d3ae4a3184d077f
Parents: ccda6d4
Author: Christopher Collins <cc...@gmail.com>
Authored: Thu Jan 28 14:00:31 2016 -0500
Committer: Christopher Collins <cc...@gmail.com>
Committed: Fri Jan 29 15:55:41 2016 -0800
----------------------------------------------------------------------
net/nimble/host/include/host/ble_gap.h | 15 +-
net/nimble/host/include/host/ble_hs.h | 4 +
net/nimble/host/include/host/ble_l2cap.h | 35 ++
net/nimble/host/src/ble_att.c | 2 +-
net/nimble/host/src/ble_att_cmd.c | 2 +-
net/nimble/host/src/ble_att_svr.c | 2 +-
net/nimble/host/src/ble_gap_conn.c | 59 +-
net/nimble/host/src/ble_gap_priv.h | 3 +
net/nimble/host/src/ble_gattc.c | 54 +-
net/nimble/host/src/ble_hs.c | 22 +-
net/nimble/host/src/ble_hs_conn.c | 2 +-
net/nimble/host/src/ble_hs_conn.h | 2 +-
net/nimble/host/src/ble_hs_misc.c | 25 +
net/nimble/host/src/ble_hs_priv.h | 4 +
net/nimble/host/src/ble_l2cap.c | 7 +-
net/nimble/host/src/ble_l2cap.h | 114 ----
net/nimble/host/src/ble_l2cap_priv.h | 44 +-
net/nimble/host/src/ble_l2cap_sig.c | 720 +++++++++++++++++-----
net/nimble/host/src/ble_l2cap_sig_cmd.c | 277 +++++++++
net/nimble/host/src/host_hci.c | 19 +-
net/nimble/host/src/host_hci_cmd.c | 2 +-
net/nimble/host/src/test/ble_att_svr_test.c | 2 +-
net/nimble/host/src/test/ble_host_hci_test.c | 2 +-
net/nimble/host/src/test/ble_hs_adv_test.c | 2 +-
net/nimble/host/src/test/ble_hs_conn_test.c | 2 +-
net/nimble/host/src/test/ble_hs_test.c | 2 +-
net/nimble/host/src/test/ble_hs_test_util.c | 3 +-
net/nimble/host/src/test/ble_l2cap_test.c | 561 +++++++++++++----
project/bleshell/src/bleshell_priv.h | 7 +-
project/bleshell/src/cmd.c | 73 ++-
project/bleshell/src/main.c | 18 +
project/bleshell/src/parse.c | 6 +-
32 files changed, 1634 insertions(+), 458 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/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 deeb1a4..3b8705e 100644
--- a/net/nimble/host/include/host/ble_gap.h
+++ b/net/nimble/host/include/host/ble_gap.h
@@ -87,13 +87,14 @@ struct hci_adv_params;
#define BLE_GAP_EVENT_CONN 0
#define BLE_GAP_EVENT_CONN_UPDATED 1
#define BLE_GAP_EVENT_CONN_UPDATE_REQ 2
-#define BLE_GAP_EVENT_CANCEL_FAILURE 3
-#define BLE_GAP_EVENT_TERM_FAILURE 4
-#define BLE_GAP_EVENT_DISC_SUCCESS 5
-#define BLE_GAP_EVENT_DISC_FINISHED 6
-#define BLE_GAP_EVENT_ADV_FINISHED 7
-#define BLE_GAP_EVENT_ADV_FAILURE 8
-#define BLE_GAP_EVENT_ADV_STOP_FAILURE 9
+#define BLE_GAP_EVENT_L2CAP_UPDATE_REQ 3
+#define BLE_GAP_EVENT_CANCEL_FAILURE 4
+#define BLE_GAP_EVENT_TERM_FAILURE 5
+#define BLE_GAP_EVENT_DISC_SUCCESS 6
+#define BLE_GAP_EVENT_DISC_FINISHED 7
+#define BLE_GAP_EVENT_ADV_FINISHED 8
+#define BLE_GAP_EVENT_ADV_FAILURE 9
+#define BLE_GAP_EVENT_ADV_STOP_FAILURE 10
struct ble_gap_conn_desc {
uint8_t peer_addr[6];
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/include/host/ble_hs.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_hs.h b/net/nimble/host/include/host/ble_hs.h
index 4e43f4c..eeff7d9 100644
--- a/net/nimble/host/include/host/ble_hs.h
+++ b/net/nimble/host/include/host/ble_hs.h
@@ -44,6 +44,7 @@
#define BLE_HS_ETIMEOUT 14
#define BLE_HS_EDONE 15
#define BLE_HS_EBUSY 16
+#define BLE_HS_EREJECT 17
#define BLE_HS_ERR_ATT_BASE 0x100 /* 256 */
#define BLE_HS_ATT_ERR(x) ((x) ? BLE_HS_ERR_ATT_BASE + (x) : 0)
@@ -51,6 +52,9 @@
#define BLE_HS_ERR_HCI_BASE 0x200 /* 512 */
#define BLE_HS_HCI_ERR(x) ((x) ? BLE_HS_ERR_HCI_BASE + (x) : 0)
+#define BLE_HS_ERR_L2C_BASE 0x300
+#define BLE_HS_L2C_ERR(x) ((x) ? BLE_HS_ERR_L2C_BASE + (x) : 0)
+
struct ble_hs_cfg {
uint16_t max_outstanding_pkts_per_conn;
uint8_t max_connections;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/include/host/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_l2cap.h b/net/nimble/host/include/host/ble_l2cap.h
index 69b77c2..06b29ec 100644
--- a/net/nimble/host/include/host/ble_l2cap.h
+++ b/net/nimble/host/include/host/ble_l2cap.h
@@ -1,13 +1,48 @@
#ifndef H_BLE_L2CAP_
#define H_BLE_L2CAP_
+struct ble_l2cap_sig_update_req;
+struct ble_hs_conn;
+
#define BLE_L2CAP_SIG_OP_REJECT 0x01
+#define BLE_L2CAP_SIG_OP_CONNECT_REQ 0x02
+#define BLE_L2CAP_SIG_OP_CONNECT_RSP 0x03
+#define BLE_L2CAP_SIG_OP_CONFIG_REQ 0x04
+#define BLE_L2CAP_SIG_OP_CONFIG_RSP 0x05
+#define BLE_L2CAP_SIG_OP_DISCONN_REQ 0x06
+#define BLE_L2CAP_SIG_OP_DISCONN_RSP 0x07
+#define BLE_L2CAP_SIG_OP_ECHO_REQ 0x08
+#define BLE_L2CAP_SIG_OP_ECHO_RSP 0x09
+#define BLE_L2CAP_SIG_OP_INFO_REQ 0x0a
+#define BLE_L2CAP_SIG_OP_INFO_RSP 0x0b
+#define BLE_L2CAP_SIG_OP_CREATE_CHAN_REQ 0x0c
+#define BLE_L2CAP_SIG_OP_CREATE_CHAN_RSP 0x0d
+#define BLE_L2CAP_SIG_OP_MOVE_CHAN_REQ 0x0e
+#define BLE_L2CAP_SIG_OP_MOVE_CHAN_RSP 0x0f
+#define BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_REQ 0x10
+#define BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_RSP 0x11
#define BLE_L2CAP_SIG_OP_UPDATE_REQ 0x12
#define BLE_L2CAP_SIG_OP_UPDATE_RSP 0x13
+#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ 0x14
+#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP 0x15
+#define BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT 0x16
#define BLE_L2CAP_SIG_OP_MAX 0x17
#define BLE_L2CAP_ERR_CMD_NOT_UNDERSTOOD 0x0000
#define BLE_L2CAP_ERR_MTU_EXCEEDED 0x0001
#define BLE_L2CAP_ERR_INVALID_CID 0x0002
+typedef void ble_l2cap_sig_update_fn(int status, void *arg);
+
+struct ble_l2cap_sig_update_params {
+ uint16_t itvl_min;
+ uint16_t itvl_max;
+ uint16_t slave_latency;
+ uint16_t timeout_multiplier;
+};
+
+int ble_l2cap_sig_update(uint16_t conn_handle,
+ struct ble_l2cap_sig_update_params *params,
+ ble_l2cap_sig_update_fn *cb, void *cb_arg);
+
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att.c b/net/nimble/host/src/ble_att.c
index 89e75b4..219a66c 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -17,7 +17,7 @@
#include <stddef.h>
#include <errno.h>
#include "ble_hs_priv.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_cmd.h"
#include "ble_att_priv.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.c b/net/nimble/host/src/ble_att_cmd.c
index 6f358fb..61ff1ac 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -21,7 +21,7 @@
#include "ble_hs_priv.h"
#include "host/ble_att.h"
#include "host/ble_uuid.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_cmd.h"
int
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index e530848..9ff872f 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -23,7 +23,7 @@
#include "host/ble_uuid.h"
#include "ble_hs_priv.h"
#include "ble_hs_priv.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_hs_conn.h"
#include "ble_att_cmd.h"
#include "ble_att_priv.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/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 7d51bf7..f51b81a 100644
--- a/net/nimble/host/src/ble_gap_conn.c
+++ b/net/nimble/host/src/ble_gap_conn.c
@@ -256,6 +256,18 @@ ble_gap_conn_update_entry_free(struct ble_gap_conn_update_entry *entry)
assert(rc == 0);
}
+static void
+ble_gap_conn_fill_desc(struct ble_hs_conn *conn,
+ struct ble_gap_conn_desc *desc)
+{
+ desc->conn_handle = conn->bhc_handle;
+ desc->peer_addr_type = conn->bhc_addr_type;
+ memcpy(desc->peer_addr, conn->bhc_addr, sizeof desc->peer_addr);
+ desc->conn_itvl = conn->bhc_itvl;
+ desc->conn_latency = conn->bhc_latency;
+ desc->supervision_timeout = conn->bhc_supervision_timeout;
+}
+
static int
ble_gap_conn_call_conn_cb(int event, int status, struct ble_hs_conn *conn,
struct ble_gap_conn_upd_params *self_params,
@@ -269,14 +281,7 @@ ble_gap_conn_call_conn_cb(int event, int status, struct ble_hs_conn *conn,
memset(&ctxt, 0, sizeof ctxt);
if (conn != NULL) {
- ctxt.desc.conn_handle = conn->bhc_handle;
- ctxt.desc.peer_addr_type = conn->bhc_addr_type;
- memcpy(ctxt.desc.peer_addr, conn->bhc_addr,
- sizeof ctxt.desc.peer_addr);
- ctxt.desc.conn_itvl = conn->bhc_itvl;
- ctxt.desc.conn_latency = conn->bhc_latency;
- ctxt.desc.supervision_timeout = conn->bhc_supervision_timeout;
-
+ ble_gap_conn_fill_desc(conn, &ctxt.desc);
cb = conn->bhc_cb;
cb_arg = conn->bhc_cb_arg;
} else {
@@ -519,6 +524,19 @@ ble_gap_conn_update_failed(struct ble_gap_conn_update_entry *entry, int status)
ble_gap_conn_update_entry_remove_free(entry);
}
+static void
+ble_gap_conn_connection_broken(uint16_t conn_handle)
+{
+ struct ble_gap_conn_update_entry *entry;
+
+ entry = ble_gap_conn_update_find(conn_handle);
+ if (entry != NULL) {
+ ble_gap_conn_update_entry_remove_free(entry);
+ }
+
+ ble_gattc_connection_broken(conn_handle);
+}
+
void
ble_gap_conn_rx_disconn_complete(struct hci_disconn_complete *evt)
{
@@ -532,14 +550,13 @@ ble_gap_conn_rx_disconn_complete(struct hci_disconn_complete *evt)
}
ble_gap_conn_call_conn_cb(BLE_GAP_EVENT_CONN, BLE_HS_ENOTCONN, conn,
NULL, NULL);
+ ble_gap_conn_connection_broken(evt->connection_handle);
ble_hs_conn_remove(conn);
ble_hs_conn_free(conn);
} else {
ble_gap_conn_notify_master_term_failure(BLE_HS_HCI_ERR(evt->status),
evt->connection_handle);
}
-
- ble_gattc_connection_broken(evt->connection_handle);
}
void
@@ -787,6 +804,8 @@ ble_gap_conn_rx_conn_complete(struct hci_le_conn_complete *evt)
if (conn != NULL) {
/* XXX: Does this ever happen? */
if (evt->status != 0) {
+ ble_gap_conn_connection_broken(evt->connection_handle);
+
ble_hs_conn_remove(conn);
ble_gap_conn_notify_connect(evt->status, conn);
ble_hs_conn_free(conn);
@@ -2061,6 +2080,26 @@ ble_gap_conn_update_params(uint16_t conn_handle,
return 0;
}
+int
+ble_gap_conn_rx_l2cap_update_req(struct ble_hs_conn *conn,
+ struct ble_gap_conn_upd_params *params)
+{
+ struct ble_gap_conn_ctxt ctxt;
+ int rc;
+
+ if (conn->bhc_cb != NULL) {
+ ble_gap_conn_fill_desc(conn, &ctxt.desc);
+ ctxt.peer_params = params;
+ ctxt.self_params = NULL;
+ rc = conn->bhc_cb(BLE_GAP_EVENT_L2CAP_UPDATE_REQ, 0, &ctxt,
+ conn->bhc_cb_arg);
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
/*****************************************************************************
* $init *
*****************************************************************************/
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_gap_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap_priv.h b/net/nimble/host/src/ble_gap_priv.h
index 76e82e7..bcea4a1 100644
--- a/net/nimble/host/src/ble_gap_priv.h
+++ b/net/nimble/host/src/ble_gap_priv.h
@@ -34,10 +34,13 @@ int ble_gap_conn_rx_conn_complete(struct hci_le_conn_complete *evt);
void ble_gap_conn_rx_disconn_complete(struct hci_disconn_complete *evt);
void ble_gap_conn_rx_update_complete(struct hci_le_conn_upd_complete *evt);
void ble_gap_conn_rx_param_req(struct hci_le_conn_param_req *evt);
+int ble_gap_conn_rx_l2cap_update_req(struct ble_hs_conn *conn,
+ struct ble_gap_conn_upd_params *params);
int ble_gap_conn_master_in_progress(void);
int ble_gap_conn_slave_in_progress(void);
int ble_gap_conn_update_in_progress(uint16_t conn_handle);
int ble_gap_conn_wl_busy(void);
+
int ble_gap_conn_init(void);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_gattc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index f79094f..4bfaef7 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -33,9 +33,9 @@
* $definitions / declarations *
*****************************************************************************/
-#define BLE_GATT_NUM_ENTRIES 16 /* XXX Configurable. */
+#define BLE_GATT_NUM_PROCS 16 /* XXX Configurable. */
#define BLE_GATT_HEARTBEAT_PERIOD 1000 /* Milliseconds. */
-#define BLE_GATT_UNRESPONSIVE_TIMEOUT 5000 /* Milliseconds. */
+#define BLE_GATT_UNRESPONSIVE_TIMEOUT 30000 /* Milliseconds. */
#define BLE_GATT_OP_NONE UINT8_MAX
#define BLE_GATT_OP_MTU 0
@@ -175,16 +175,16 @@ struct ble_gattc_proc {
};
/** Procedure has a tx pending. */
-#define BLE_GATT_ENTRY_F_PENDING 0x01
+#define BLE_GATT_PROC_F_PENDING 0x01
/** Procedure currently expects an ATT response. */
-#define BLE_GATT_ENTRY_F_EXPECTING 0x02
+#define BLE_GATT_PROC_F_EXPECTING 0x02
/** Procedure failed to tx due to too many outstanding txes. */
-#define BLE_GATT_ENTRY_F_CONGESTED 0x04
+#define BLE_GATT_PROC_F_CONGESTED 0x04
/** Procedure failed to tx due to memory exhaustion. */
-#define BLE_GATT_ENTRY_F_NO_MEM 0x08
+#define BLE_GATT_PROC_F_NO_MEM 0x08
/**
* Handles unresponsive timeouts and periodic retries in case of resource
@@ -640,7 +640,7 @@ ble_gattc_proc_matches(struct ble_gattc_proc *proc, uint16_t conn_handle,
}
if (expecting_only &&
- !(proc->flags & BLE_GATT_ENTRY_F_EXPECTING)) {
+ !(proc->flags & BLE_GATT_PROC_F_EXPECTING)) {
return 0;
}
@@ -691,10 +691,10 @@ ble_gattc_proc_find(uint16_t conn_handle, uint8_t op, int expecting_only,
static void
ble_gattc_proc_set_pending(struct ble_gattc_proc *proc)
{
- assert(!(proc->flags & BLE_GATT_ENTRY_F_PENDING));
+ assert(!(proc->flags & BLE_GATT_PROC_F_PENDING));
- proc->flags &= ~BLE_GATT_ENTRY_F_EXPECTING;
- proc->flags |= BLE_GATT_ENTRY_F_PENDING;
+ proc->flags &= ~BLE_GATT_PROC_F_EXPECTING;
+ proc->flags |= BLE_GATT_PROC_F_PENDING;
ble_hs_kick_gatt();
}
@@ -706,11 +706,11 @@ static void
ble_gattc_proc_set_expecting(struct ble_gattc_proc *proc,
struct ble_gattc_proc *prev)
{
- assert(!(proc->flags & BLE_GATT_ENTRY_F_EXPECTING));
+ assert(!(proc->flags & BLE_GATT_PROC_F_EXPECTING));
ble_gattc_proc_remove(proc, prev);
- proc->flags &= ~BLE_GATT_ENTRY_F_PENDING;
- proc->flags |= BLE_GATT_ENTRY_F_EXPECTING;
+ proc->flags &= ~BLE_GATT_PROC_F_PENDING;
+ proc->flags |= BLE_GATT_PROC_F_EXPECTING;
proc->tx_time = os_time_get();
STAILQ_INSERT_TAIL(&ble_gattc_list, proc, next);
}
@@ -763,9 +763,9 @@ ble_gattc_new_proc(uint16_t conn_handle, uint8_t op,
static int
ble_gattc_proc_can_pend(struct ble_gattc_proc *proc)
{
- return !(proc->flags & (BLE_GATT_ENTRY_F_CONGESTED |
- BLE_GATT_ENTRY_F_NO_MEM |
- BLE_GATT_ENTRY_F_EXPECTING));
+ return !(proc->flags & (BLE_GATT_PROC_F_CONGESTED |
+ BLE_GATT_PROC_F_NO_MEM |
+ BLE_GATT_PROC_F_EXPECTING));
}
/**
@@ -786,11 +786,11 @@ ble_gattc_tx_postpone_chk(struct ble_gattc_proc *proc, int rc)
{
switch (rc) {
case BLE_HS_ECONGESTED:
- proc->flags |= BLE_GATT_ENTRY_F_CONGESTED;
+ proc->flags |= BLE_GATT_PROC_F_CONGESTED;
return 1;
case BLE_HS_ENOMEM:
- proc->flags |= BLE_GATT_ENTRY_F_NO_MEM;
+ proc->flags |= BLE_GATT_PROC_F_NO_MEM;
return 1;
default:
@@ -833,12 +833,12 @@ ble_gattc_heartbeat(void *unused)
now = os_time_get();
STAILQ_FOREACH(proc, &ble_gattc_list, next) {
- if (proc->flags & BLE_GATT_ENTRY_F_NO_MEM) {
- proc->flags &= ~BLE_GATT_ENTRY_F_NO_MEM;
+ if (proc->flags & BLE_GATT_PROC_F_NO_MEM) {
+ proc->flags &= ~BLE_GATT_PROC_F_NO_MEM;
if (ble_gattc_proc_can_pend(proc)) {
ble_gattc_proc_set_pending(proc);
}
- } else if (proc->flags & BLE_GATT_ENTRY_F_EXPECTING) {
+ } else if (proc->flags & BLE_GATT_PROC_F_EXPECTING) {
if (now - proc->tx_time >= BLE_GATT_UNRESPONSIVE_TIMEOUT) {
rc = ble_gap_conn_terminate(proc->conn_handle);
assert(rc == 0); /* XXX */
@@ -4070,7 +4070,7 @@ ble_gattc_wakeup(void)
while (proc != NULL) {
next = STAILQ_NEXT(proc, next);
- if (proc->flags & BLE_GATT_ENTRY_F_PENDING) {
+ if (proc->flags & BLE_GATT_PROC_F_PENDING) {
dispatch = ble_gattc_dispatch_get(proc->op);
rc = dispatch->kick_cb(proc);
switch (rc) {
@@ -4082,7 +4082,7 @@ ble_gattc_wakeup(void)
case BLE_HS_EAGAIN:
/* Transmit failed due to resource shortage. Reschedule. */
- proc->flags &= ~BLE_GATT_ENTRY_F_PENDING;
+ proc->flags &= ~BLE_GATT_PROC_F_PENDING;
/* Current proc remains; reseat prev. */
prev = proc;
break;
@@ -4148,9 +4148,9 @@ ble_gattc_connection_txable(uint16_t conn_handle)
STAILQ_FOREACH(proc, &ble_gattc_list, next) {
if (proc->conn_handle == conn_handle &&
- proc->flags & BLE_GATT_ENTRY_F_CONGESTED) {
+ proc->flags & BLE_GATT_PROC_F_CONGESTED) {
- proc->flags &= ~BLE_GATT_ENTRY_F_CONGESTED;
+ proc->flags &= ~BLE_GATT_PROC_F_CONGESTED;
if (ble_gattc_proc_can_pend(proc)) {
ble_gattc_proc_set_pending(proc);
}
@@ -4189,7 +4189,7 @@ ble_gattc_init(void)
free(ble_gattc_proc_mem);
ble_gattc_proc_mem = malloc(
- OS_MEMPOOL_BYTES(BLE_GATT_NUM_ENTRIES,
+ OS_MEMPOOL_BYTES(BLE_GATT_NUM_PROCS,
sizeof (struct ble_gattc_proc)));
if (ble_gattc_proc_mem == NULL) {
rc = BLE_HS_ENOMEM;
@@ -4197,7 +4197,7 @@ ble_gattc_init(void)
}
rc = os_mempool_init(&ble_gattc_proc_pool,
- BLE_GATT_NUM_ENTRIES,
+ BLE_GATT_NUM_PROCS,
sizeof (struct ble_gattc_proc),
ble_gattc_proc_mem,
"ble_gattc_proc_pool");
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_hs.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index 037b8a0..2c09518 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -74,6 +74,7 @@ struct os_mbuf_pool ble_hs_mbuf_pool;
struct os_eventq ble_hs_evq;
static struct os_event ble_hs_kick_hci_ev;
static struct os_event ble_hs_kick_gatt_ev;
+static struct os_event ble_hs_kick_l2cap_sig_ev;
static struct os_mqueue ble_hs_rx_q;
static struct os_mqueue ble_hs_tx_q;
@@ -141,6 +142,10 @@ ble_hs_task_handler(void *arg)
ble_gattc_wakeup();
break;
+ case BLE_HS_KICK_L2CAP_SIG_EVENT:
+ ble_l2cap_sig_wakeup();
+ break;
+
default:
assert(0);
break;
@@ -184,7 +189,7 @@ ble_hs_tx_data(struct os_mbuf *om)
}
/**
- * Wakes the BLE host task so that it can process hci_batch events.
+ * Wakes the BLE host task so that it can process hci events.
*/
void
ble_hs_kick_hci(void)
@@ -193,7 +198,7 @@ ble_hs_kick_hci(void)
}
/**
- * Wakes the BLE host task so that it can process att_batch events.
+ * Wakes the BLE host task so that it can process GATT events.
*/
void
ble_hs_kick_gatt(void)
@@ -202,6 +207,15 @@ ble_hs_kick_gatt(void)
}
/**
+ * Wakes the BLE host task so that it can process L2CAP sig events.
+ */
+void
+ble_hs_kick_l2cap_sig(void)
+{
+ os_eventq_put(&ble_hs_evq, &ble_hs_kick_l2cap_sig_ev);
+}
+
+/**
* Initializes the host portion of the BLE stack.
*/
int
@@ -290,6 +304,10 @@ ble_hs_init(uint8_t prio)
ble_hs_kick_gatt_ev.ev_type = BLE_HS_KICK_GATT_EVENT;
ble_hs_kick_gatt_ev.ev_arg = NULL;
+ ble_hs_kick_l2cap_sig_ev.ev_queued = 0;
+ ble_hs_kick_l2cap_sig_ev.ev_type = BLE_HS_KICK_L2CAP_SIG_EVENT;
+ ble_hs_kick_l2cap_sig_ev.ev_arg = NULL;
+
os_mqueue_init(&ble_hs_rx_q, NULL);
os_mqueue_init(&ble_hs_tx_q, NULL);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_hs_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.c b/net/nimble/host/src/ble_hs_conn.c
index 26e7d6c..1ed3849 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -20,7 +20,7 @@
#include "os/os.h"
#include "host/host_hci.h"
#include "ble_hs_priv.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_l2cap_sig.h"
#include "ble_att_priv.h"
#include "ble_gatt_priv.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_hs_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.h b/net/nimble/host/src/ble_hs_conn.h
index 2e6c62d..bdea85c 100644
--- a/net/nimble/host/src/ble_hs_conn.h
+++ b/net/nimble/host/src/ble_hs_conn.h
@@ -19,7 +19,7 @@
#include "os/queue.h"
#include "host/ble_gap.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_priv.h"
#include "ble_gatt_priv.h"
struct hci_le_conn_complete;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_hs_misc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
index 42f4596..085c743 100644
--- a/net/nimble/host/src/ble_hs_misc.c
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include "os/os.h"
+#include "console/console.h"
#include "ble_hs_priv.h"
int
@@ -37,3 +38,27 @@ ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
return 0;
}
+
+void
+ble_hs_misc_log_mbuf(struct os_mbuf *om)
+{
+ uint8_t u8;
+ int i;
+
+ for (i = 0; i < OS_MBUF_PKTLEN(om); i++) {
+ os_mbuf_copydata(om, i, 1, &u8);
+ console_printf("0x%02x ", u8);
+ }
+}
+
+void
+ble_hs_misc_log_flat_buf(void *data, int len)
+{
+ uint8_t *u8ptr;
+ int i;
+
+ u8ptr = data;
+ for (i = 0; i < len; i++) {
+ console_printf("0x%02x ", u8ptr[i]);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_hs_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_priv.h b/net/nimble/host/src/ble_hs_priv.h
index 80b5997..119dc32 100644
--- a/net/nimble/host/src/ble_hs_priv.h
+++ b/net/nimble/host/src/ble_hs_priv.h
@@ -25,6 +25,7 @@ struct os_mempool;
#define BLE_HOST_HCI_EVENT_CTLR_EVENT (OS_EVENT_T_PERUSER + 0)
#define BLE_HS_KICK_HCI_EVENT (OS_EVENT_T_PERUSER + 1)
#define BLE_HS_KICK_GATT_EVENT (OS_EVENT_T_PERUSER + 2)
+#define BLE_HS_KICK_L2CAP_SIG_EVENT (OS_EVENT_T_PERUSER + 3)
extern struct os_mbuf_pool ble_hs_mbuf_pool;
extern struct os_eventq ble_hs_evq;
@@ -34,9 +35,12 @@ int ble_hs_rx_data(struct os_mbuf *om);
int ble_hs_tx_data(struct os_mbuf *om);
void ble_hs_kick_hci(void);
void ble_hs_kick_gatt(void);
+void ble_hs_kick_l2cap_sig(void);
int ble_hs_misc_malloc_mempool(void **mem, struct os_mempool *pool,
int num_entries, int entry_size, char *name);
+void ble_hs_misc_log_mbuf(struct os_mbuf *om);
+void ble_hs_misc_log_flat_buf(void *data, int len);
void ble_hs_cfg_init(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_l2cap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_l2cap.c
index 1b0a819..008f5bc 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -23,7 +23,7 @@
#include "ble_hs_priv.h"
#include "host/host_hci.h"
#include "ble_hs_conn.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
_Static_assert(sizeof (struct ble_l2cap_hdr) == BLE_L2CAP_HDR_SZ,
"struct ble_l2cap_hdr must be 4 bytes");
@@ -288,6 +288,11 @@ ble_l2cap_init(void)
goto err;
}
+ rc = ble_l2cap_sig_init();
+ if (rc != 0) {
+ goto err;
+ }
+
return 0;
err:
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.h b/net/nimble/host/src/ble_l2cap.h
deleted file mode 100644
index d32419b..0000000
--- a/net/nimble/host/src/ble_l2cap.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * 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.
- */
-
-#ifndef H_L2CAP_PRIV_
-#define H_L2CAP_PRIV_
-
-#include "host/ble_l2cap.h"
-#include <inttypes.h>
-#include "os/queue.h"
-#include "os/os_mbuf.h"
-struct ble_hs_conn;
-struct hci_data_hdr;
-
-#define BLE_L2CAP_SIG_HDR_SZ 4
-struct ble_l2cap_sig_hdr {
- uint8_t op;
- uint8_t identifier;
- uint16_t length;
-};
-
-#define BLE_L2CAP_SIG_REJECT_MIN_SZ 2
-struct ble_l2cap_sig_reject {
- uint16_t reason;
-};
-
-#define BLE_L2CAP_SIG_UPDATE_REQ_SZ 8
-struct ble_l2cap_sig_update_req {
- uint16_t itvl_min;
- uint16_t itvl_max;
- uint16_t slave_latency;
- uint16_t timeout_multiplier;
-};
-
-#define BLE_L2CAP_SIG_UPDATE_RSP_SZ 2
-struct ble_l2cap_sig_update_rsp {
- uint16_t result;
-};
-
-
-#define BLE_L2CAP_CID_ATT 4
-#define BLE_L2CAP_CID_SIG 5
-
-#define BLE_L2CAP_HDR_SZ 4
-
-struct ble_l2cap_hdr
-{
- uint16_t blh_len;
- uint16_t blh_cid;
-};
-
-struct ble_l2cap_chan;
-
-typedef int ble_l2cap_rx_fn(struct ble_hs_conn *conn,
- struct ble_l2cap_chan *chan,
- struct os_mbuf **om);
-
-typedef int ble_l2cap_tx_fn(struct ble_hs_conn *conn,
- struct ble_l2cap_chan *chan);
-
-typedef uint8_t ble_l2cap_chan_flags;
-#define BLE_L2CAP_CHAN_F_TXED_MTU 0x01 /* We have sent our MTU. */
-
-struct ble_l2cap_chan
-{
- SLIST_ENTRY(ble_l2cap_chan) blc_next;
- uint16_t blc_cid;
- uint16_t blc_my_mtu;
- uint16_t blc_peer_mtu; /* 0 if not exchanged. */
- uint16_t blc_default_mtu;
- ble_l2cap_chan_flags blc_flags;
-
- struct os_mbuf *blc_rx_buf;
- uint16_t blc_rx_len; /* Length of current reassembled rx packet. */
-
- ble_l2cap_rx_fn *blc_rx_fn;
-};
-
-
-SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan);
-
-struct ble_l2cap_chan *ble_l2cap_chan_alloc(void);
-void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
-
-uint16_t ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan);
-
-int ble_l2cap_parse_hdr(struct os_mbuf *om, int off,
- struct ble_l2cap_hdr *l2cap_hdr);
-struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
- uint16_t len);
-
-int ble_l2cap_rx(struct ble_hs_conn *connection,
- struct hci_data_hdr *hci_hdr,
- struct os_mbuf *om);
-int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- struct os_mbuf *om);
-
-int ble_l2cap_init(void);
-
-extern struct os_mbuf_pool ble_l2cap_mbuf_pool;
-
-#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_l2cap_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_priv.h b/net/nimble/host/src/ble_l2cap_priv.h
index d32419b..4f8940b 100644
--- a/net/nimble/host/src/ble_l2cap_priv.h
+++ b/net/nimble/host/src/ble_l2cap_priv.h
@@ -49,6 +49,9 @@ struct ble_l2cap_sig_update_rsp {
uint16_t result;
};
+#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT 0x0000
+#define BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT 0x0001
+
#define BLE_L2CAP_CID_ATT 4
#define BLE_L2CAP_CID_SIG 5
@@ -91,15 +94,44 @@ struct ble_l2cap_chan
SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan);
+int ble_l2cap_parse_hdr(struct os_mbuf *om, int off,
+ struct ble_l2cap_hdr *l2cap_hdr);
+struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
+ uint16_t len);
+
+int ble_l2cap_sig_hdr_parse(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr);
+int ble_l2cap_sig_hdr_write(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr);
+int ble_l2cap_sig_reject_write(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_reject *cmd);
+int ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ uint8_t id, uint16_t reason);
+int ble_l2cap_sig_update_req_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_req *req);
+int ble_l2cap_sig_update_req_write(void *payload, int len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_update_req *req);
+int ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan, uint8_t id,
+ struct ble_l2cap_sig_update_req *req);
+int ble_l2cap_sig_update_rsp_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_rsp *cmd);
+int ble_l2cap_sig_update_rsp_write(void *payload, int len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_update_rsp *cmd);
+int ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan, uint8_t id,
+ uint16_t result);
+
+
struct ble_l2cap_chan *ble_l2cap_chan_alloc(void);
void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
uint16_t ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan);
-int ble_l2cap_parse_hdr(struct os_mbuf *om, int off,
- struct ble_l2cap_hdr *l2cap_hdr);
-struct os_mbuf *ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid,
- uint16_t len);
int ble_l2cap_rx(struct ble_hs_conn *connection,
struct hci_data_hdr *hci_hdr,
@@ -107,8 +139,8 @@ int ble_l2cap_rx(struct ble_hs_conn *connection,
int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
struct os_mbuf *om);
+void ble_l2cap_sig_wakeup(void);
+int ble_l2cap_sig_init(void);
int ble_l2cap_init(void);
-extern struct os_mbuf_pool ble_l2cap_mbuf_pool;
-
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_l2cap_sig.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c
index cdfa9ff..43d0125 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -21,25 +21,149 @@
#include "nimble/ble.h"
#include "ble_hs_priv.h"
#include "ble_hs_conn.h"
+#include "ble_gap_priv.h"
#include "ble_l2cap_priv.h"
#include "ble_att_priv.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_l2cap_sig.h"
+/*****************************************************************************
+ * $definitions / declarations *
+ *****************************************************************************/
+
+#define BLE_L2CAP_SIG_NUM_PROCS 16 /* XXX Configurable. */
+#define BLE_L2CAP_SIG_HEARTBEAT_PERIOD 1000 /* Milliseconds. */
+#define BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT 30000 /* Milliseconds. */
+
+#define BLE_L2CAP_SIG_PROC_OP_UPDATE 0
+#define BLE_L2CAP_SIG_PROC_OP_MAX 1
+
+struct ble_l2cap_sig_proc {
+ STAILQ_ENTRY(ble_l2cap_sig_proc) next;
+
+ uint8_t op;
+ uint8_t id;
+ uint8_t flags;
+ uint16_t conn_handle;
+ uint32_t tx_time; /* OS ticks. */
+ union {
+ struct {
+ struct ble_l2cap_sig_update_params params;
+ ble_l2cap_sig_update_fn *cb;
+ void *cb_arg;
+ } update;
+ };
+};
+
+/** Procedure has a tx pending. */
+#define BLE_L2CAP_SIG_PROC_F_PENDING 0x01
+
+/** Procedure currently expects an ATT response. */
+#define BLE_L2CAP_SIG_PROC_F_EXPECTING 0x02
+
+/** Procedure failed to tx due to too many outstanding txes. */
+#define BLE_L2CAP_SIG_PROC_F_CONGESTED 0x04
+
+/** Procedure failed to tx due to memory exhaustion. */
+#define BLE_L2CAP_SIG_PROC_F_NO_MEM 0x08
+
+/**
+ * Handles unresponsive timeouts and periodic retries in case of resource
+ * shortage.
+ */
+static struct os_callout_func ble_l2cap_sig_heartbeat_timer;
+
+typedef int ble_l2cap_sig_kick_fn(struct ble_l2cap_sig_proc *proc);
+
typedef int ble_l2cap_sig_rx_fn(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct ble_l2cap_sig_hdr *hdr,
struct os_mbuf **om);
+static int ble_l2cap_sig_rx_noop(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct os_mbuf **om);
static int ble_l2cap_sig_update_req_rx(struct ble_hs_conn *conn,
struct ble_l2cap_chan *chan,
struct ble_l2cap_sig_hdr *hdr,
struct os_mbuf **om);
+static int ble_l2cap_sig_update_rsp_rx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct os_mbuf **om);
-static ble_l2cap_sig_rx_fn *ble_l2cap_sig_dispatch[] = {
- [BLE_L2CAP_SIG_OP_UPDATE_REQ] = ble_l2cap_sig_update_req_rx,
+static int ble_l2cap_sig_update_kick(struct ble_l2cap_sig_proc *proc);
+
+static ble_l2cap_sig_rx_fn * const ble_l2cap_sig_dispatch[] = {
+ [BLE_L2CAP_SIG_OP_REJECT] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_CONNECT_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_CONFIG_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_DISCONN_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_ECHO_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_INFO_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_CREATE_CHAN_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_MOVE_CHAN_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_RSP] = ble_l2cap_sig_rx_noop,
+ [BLE_L2CAP_SIG_OP_UPDATE_REQ] = ble_l2cap_sig_update_req_rx,
+ [BLE_L2CAP_SIG_OP_UPDATE_RSP] = ble_l2cap_sig_update_rsp_rx,
+ [BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP] = ble_l2cap_sig_rx_noop,
};
+static ble_l2cap_sig_kick_fn * const ble_l2cap_sig_kick[] = {
+ [BLE_L2CAP_SIG_PROC_OP_UPDATE] = ble_l2cap_sig_update_kick,
+};
+
+static uint8_t ble_l2cap_sig_cur_id;
+
+static void *ble_l2cap_sig_proc_mem;
+static struct os_mempool ble_l2cap_sig_proc_pool;
+
+static STAILQ_HEAD(, ble_l2cap_sig_proc) ble_l2cap_sig_list;
+
+/*****************************************************************************
+ * $debug *
+ *****************************************************************************/
+
+/**
+ * Ensures all procedure entries are in a valid state.
+ */
+static void
+ble_l2cap_sig_assert_sanity(void)
+{
+#ifdef BLE_HS_DEBUG
+ struct ble_l2cap_sig_proc *proc;
+ unsigned mask;
+ int num_set;
+
+ STAILQ_FOREACH(proc, &ble_l2cap_sig_list, next) {
+ /* Ensure exactly one flag is set. */
+ num_set = 0;
+ mask = 0x01;
+ while (mask <= UINT8_MAX) {
+ if (proc->flags & mask) {
+ num_set++;
+ }
+ mask <<= 1;
+ }
+
+ assert(num_set == 1);
+ }
+#endif
+}
+
+static uint8_t
+ble_l2cap_sig_next_id(void)
+{
+ ble_l2cap_sig_cur_id++;
+ if (ble_l2cap_sig_cur_id == 0) {
+ /* An ID of 0 is illegal. */
+ ble_l2cap_sig_cur_id = 1;
+ }
+
+ return ble_l2cap_sig_cur_id;
+}
+
static ble_l2cap_sig_rx_fn *
ble_l2cap_sig_dispatch_get(uint8_t op)
{
@@ -50,191 +174,248 @@ ble_l2cap_sig_dispatch_get(uint8_t op)
return ble_l2cap_sig_dispatch[op];
}
-static int
-ble_l2cap_sig_hdr_parse(void *payload, uint16_t len,
- struct ble_l2cap_sig_hdr *hdr)
+static ble_l2cap_sig_kick_fn *
+ble_l2cap_sig_kick_get(uint8_t op)
{
- uint8_t *u8ptr;
-
- if (len < BLE_L2CAP_SIG_HDR_SZ) {
- return BLE_HS_EBADDATA;
+ if (op > BLE_L2CAP_SIG_PROC_OP_MAX) {
+ return NULL;
}
- u8ptr = payload;
- hdr->op = u8ptr[0];
- hdr->identifier = u8ptr[1];
- hdr->length = le16toh(u8ptr + 2);
-
- return 0;
+ return ble_l2cap_sig_kick[op];
}
+/**
+ * Determines if the specified proc entry's "pending" flag can be set.
+ */
static int
-ble_l2cap_sig_hdr_write(void *payload, uint16_t len,
- struct ble_l2cap_sig_hdr *hdr)
+ble_l2cap_sig_proc_can_pend(struct ble_l2cap_sig_proc *proc)
{
- uint8_t *u8ptr;
+ return !(proc->flags & (BLE_L2CAP_SIG_PROC_F_CONGESTED |
+ BLE_L2CAP_SIG_PROC_F_NO_MEM |
+ BLE_L2CAP_SIG_PROC_F_EXPECTING));
+}
- if (len < BLE_L2CAP_SIG_HDR_SZ) {
- return BLE_HS_EBADDATA;
- }
+/**
+ * Allocates a proc entry.
+ *
+ * @return An entry on success; null on failure.
+ */
+static struct ble_l2cap_sig_proc *
+ble_l2cap_sig_proc_alloc(void)
+{
+ struct ble_l2cap_sig_proc *proc;
- u8ptr = payload;
- u8ptr[0] = hdr->op;
- u8ptr[1] = hdr->identifier;
- htole16(u8ptr + 2, hdr->length);
+ proc = os_memblock_get(&ble_l2cap_sig_proc_pool);
+ if (proc != NULL) {
+ memset(proc, 0, sizeof *proc);
+ }
- return 0;
+ return proc;
}
-static int
-ble_l2cap_sig_reject_write(void *payload, uint16_t len,
- struct ble_l2cap_sig_hdr *hdr,
- struct ble_l2cap_sig_reject *cmd)
+/**
+ * Frees the specified proc entry. No-op if passed a null pointer.
+ */
+static void
+ble_l2cap_sig_proc_free(struct ble_l2cap_sig_proc *proc)
{
- uint8_t *u8ptr;
int rc;
- u8ptr = payload;
- rc = ble_l2cap_sig_hdr_write(u8ptr, len, hdr);
- if (rc != 0) {
- return rc;
+ if (proc != NULL) {
+ rc = os_memblock_put(&ble_l2cap_sig_proc_pool, proc);
+ assert(rc == 0);
}
+}
- u8ptr += BLE_L2CAP_SIG_HDR_SZ;
- len -= BLE_L2CAP_SIG_HDR_SZ;
-
- if (len < BLE_L2CAP_SIG_REJECT_MIN_SZ) {
- return BLE_HS_EMSGSIZE;
+/**
+ * Removes the specified proc entry from the global list without freeing it.
+ *
+ * @param proc The proc to remove.
+ * @param prev The proc that is previous to "proc" in the
+ * list; null if "proc" is the list head.
+ */
+static void
+ble_l2cap_sig_proc_remove(struct ble_l2cap_sig_proc *proc,
+ struct ble_l2cap_sig_proc *prev)
+{
+ if (prev == NULL) {
+ assert(STAILQ_FIRST(&ble_l2cap_sig_list) == proc);
+ STAILQ_REMOVE_HEAD(&ble_l2cap_sig_list, next);
+ } else {
+ assert(STAILQ_NEXT(prev, next) == proc);
+ STAILQ_NEXT(prev, next) = STAILQ_NEXT(proc, next);
}
+}
- htole16(u8ptr, cmd->reason);
-
- return 0;
+/**
+ * Removes and frees the speicifed proc entry.
+ *
+ * @param proc The proc to remove and free.
+ * @param prev The proc that is previous to "proc" in the
+ * list; null if "proc" is the list head.
+ */
+static void
+ble_l2cap_sig_proc_remove_free(struct ble_l2cap_sig_proc *proc,
+ struct ble_l2cap_sig_proc *prev)
+{
+ ble_l2cap_sig_proc_remove(proc, prev);
+ ble_l2cap_sig_proc_free(proc);
}
static int
-ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
- uint8_t identifier, uint16_t reason)
+ble_l2cap_sig_new_proc(uint16_t conn_handle, uint8_t op,
+ struct ble_l2cap_sig_proc **out_proc)
{
- /* XXX: Add support for optional data field. */
+ struct ble_hs_conn *conn;
- struct ble_l2cap_sig_reject cmd;
- struct ble_l2cap_sig_hdr hdr;
- struct os_mbuf *txom;
- void *v;
- int rc;
+ *out_proc = NULL;
- txom = ble_att_get_pkthdr();
- if (txom == NULL) {
- return BLE_HS_ENOMEM;
+ /* Ensure we have a connection with the specified handle. */
+ conn = ble_hs_conn_find(conn_handle);
+ if (conn == NULL) {
+ return BLE_HS_ENOTCONN;
}
- v = os_mbuf_extend(txom,
- BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_REJECT_MIN_SZ);
- if (v == NULL) {
+ *out_proc = ble_l2cap_sig_proc_alloc();
+ if (*out_proc == NULL) {
return BLE_HS_ENOMEM;
}
- hdr.op = BLE_L2CAP_SIG_OP_REJECT;
- hdr.identifier = identifier;
- hdr.length = BLE_L2CAP_SIG_REJECT_MIN_SZ;
- cmd.reason = reason;
+ memset(*out_proc, 0, sizeof **out_proc);
+ (*out_proc)->op = op;
+ (*out_proc)->conn_handle = conn_handle;
- rc = ble_l2cap_sig_reject_write(
- v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_REJECT_MIN_SZ, &hdr, &cmd);
- if (rc != 0) {
- return rc;
- }
+ STAILQ_INSERT_TAIL(&ble_l2cap_sig_list, *out_proc, next);
- rc = ble_l2cap_tx(conn, chan, txom);
- return rc;
+ return 0;
}
+/**
+ * Tests if a proc entry fits the specified criteria.
+ *
+ * @param proc The procedure to test.
+ * @param conn_handle The connection handle to match against.
+ * @param op The op code to match against/
+ * @param id The identifier to match against.
+ * @param expecting_only 1=Only match entries expecting a response;
+ * 0=Ignore this criterion.
+ *
+ * @return 1 if the proc matches; 0 otherwise.
+ */
static int
-ble_l2cap_sig_update_req_parse(void *payload, int len,
- struct ble_l2cap_sig_update_req *req)
+ble_l2cap_sig_proc_matches(struct ble_l2cap_sig_proc *proc,
+ uint16_t conn_handle, uint8_t op, uint8_t id,
+ int expecting_only)
{
- uint8_t *u8ptr;
+ if (conn_handle != proc->conn_handle) {
+ return 0;
+ }
- if (len < BLE_L2CAP_SIG_UPDATE_REQ_SZ) {
- return BLE_HS_EBADDATA;
+ if (op != proc->op) {
+ return 0;
}
- u8ptr = payload;
+ if (id != proc->id) {
+ return 0;
+ }
- req->itvl_min = le16toh(u8ptr + 0);
- req->itvl_max = le16toh(u8ptr + 2);
- req->slave_latency = le16toh(u8ptr + 4);
- req->timeout_multiplier = le16toh(u8ptr + 6);
+ if (expecting_only &&
+ !(proc->flags & BLE_L2CAP_SIG_PROC_F_EXPECTING)) {
- return 0;
+ return 0;
+ }
+
+ return 1;
}
-static int
-ble_l2cap_sig_update_rsp_write(void *payload, int len,
- struct ble_l2cap_sig_hdr *hdr,
- struct ble_l2cap_sig_update_rsp *cmd)
+/**
+ * Searched the global proc list for an entry that fits the specified criteria.
+ *
+ * @param conn_handle The connection handle to match against.
+ * @param op The op code to match against.
+ * @param id The identifier to match against.
+ * @param expecting_only 1=Only match entries expecting a response;
+ * 0=Ignore this criterion.
+ * @param out_prev On success, the address of the result's
+ * previous entry gets written here. Pass
+ * null if you don't need this information.
+ *
+ * @return 1 if the proc matches; 0 otherwise.
+ */
+static struct ble_l2cap_sig_proc *
+ble_l2cap_sig_proc_find(uint16_t conn_handle, uint8_t op, uint8_t id,
+ int expecting_only,
+ struct ble_l2cap_sig_proc **out_prev)
{
- uint8_t *u8ptr;
- int rc;
-
- u8ptr = payload;
- rc = ble_l2cap_sig_hdr_write(u8ptr, len, hdr);
- if (rc != 0) {
- return rc;
+ struct ble_l2cap_sig_proc *proc;
+ struct ble_l2cap_sig_proc *prev;
+
+ prev = NULL;
+ STAILQ_FOREACH(proc, &ble_l2cap_sig_list, next) {
+ if (ble_l2cap_sig_proc_matches(proc, conn_handle, op, id,
+ expecting_only)) {
+ if (out_prev != NULL) {
+ *out_prev = prev;
+ }
+ return proc;
+ }
+
+ prev = proc;
}
- u8ptr += BLE_L2CAP_SIG_HDR_SZ;
- len -= BLE_L2CAP_SIG_HDR_SZ;
+ return NULL;
+}
- if (len < BLE_L2CAP_SIG_UPDATE_RSP_SZ) {
- return BLE_HS_EMSGSIZE;
- }
+/**
+ * Sets the specified proc entry's "pending" flag (i.e., indicates that the
+ * L2CAP sig procedure is stalled until it transmits its next request.
+ */
+static void
+ble_l2cap_sig_proc_set_pending(struct ble_l2cap_sig_proc *proc)
+{
+ assert(!(proc->flags & BLE_L2CAP_SIG_PROC_F_PENDING));
- htole16(u8ptr, cmd->result);
+ proc->flags &= ~BLE_L2CAP_SIG_PROC_F_EXPECTING;
+ proc->flags |= BLE_L2CAP_SIG_PROC_F_PENDING;
+ ble_hs_kick_l2cap_sig();
+}
- return 0;
+/**
+ * Sets the specified proc entry's "expecting" flag (i.e., indicates that the
+ * L2CAP sig procedure is stalled until it receives a response.
+ */
+static void
+ble_l2cap_sig_proc_set_expecting(struct ble_l2cap_sig_proc *proc,
+ struct ble_l2cap_sig_proc *prev)
+{
+ assert(!(proc->flags & BLE_L2CAP_SIG_PROC_F_EXPECTING));
+
+ ble_l2cap_sig_proc_remove(proc, prev);
+ proc->flags &= ~BLE_L2CAP_SIG_PROC_F_PENDING;
+ proc->flags |= BLE_L2CAP_SIG_PROC_F_EXPECTING;
+ proc->tx_time = os_time_get();
+ STAILQ_INSERT_TAIL(&ble_l2cap_sig_list, proc, next);
}
static int
-ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
- struct ble_l2cap_chan *chan,
- uint16_t identifier, uint16_t result)
+ble_l2cap_sig_rx_noop(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct os_mbuf **om)
{
- struct ble_l2cap_sig_update_rsp rsp;
- struct ble_l2cap_sig_hdr hdr;
- struct os_mbuf *txom;
- void *v;
- int rc;
+ return 0;
+}
- txom = ble_att_get_pkthdr();
- if (txom == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
- }
+/*****************************************************************************
+ * $update *
+ *****************************************************************************/
- v = os_mbuf_extend(txom,
- BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
- if (v == NULL) {
- rc = BLE_HS_ENOMEM;
- goto err;
+static void
+ble_l2cap_sig_update_call_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+ if (proc->update.cb != NULL) {
+ proc->update.cb(status, proc->update.cb_arg);
}
-
- hdr.op = BLE_L2CAP_SIG_OP_UPDATE_RSP;
- hdr.identifier = identifier;
- hdr.length = BLE_L2CAP_SIG_UPDATE_RSP_SZ;
- rsp.result = result;
-
- rc = ble_l2cap_sig_update_rsp_write(
- v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ, &hdr, &rsp);
- assert(rc == 0);
-
- rc = ble_l2cap_tx(conn, chan, txom);
- return rc;
-
-err:
- os_mbuf_free_chain(txom);
- return rc;
}
static int
@@ -245,6 +426,7 @@ ble_l2cap_sig_update_req_rx(struct ble_hs_conn *conn,
{
struct ble_l2cap_sig_update_req req;
struct ble_gap_conn_upd_params params;
+ uint16_t l2cap_result;
int rc;
*om = os_mbuf_pullup(*om, BLE_L2CAP_SIG_UPDATE_REQ_SZ);
@@ -262,12 +444,6 @@ ble_l2cap_sig_update_req_rx(struct ble_hs_conn *conn,
return BLE_HS_ENOTSUP;
}
- /* XXX: For now, always accept. */
- rc = ble_l2cap_sig_update_rsp_tx(conn, chan, hdr->identifier, 0);
- if (rc != 0) {
- return rc;
- }
-
params.itvl_min = req.itvl_min;
params.itvl_max = req.itvl_max;
params.latency = req.slave_latency;
@@ -275,7 +451,117 @@ ble_l2cap_sig_update_req_rx(struct ble_hs_conn *conn,
params.min_ce_len = BLE_GAP_INITIAL_CONN_MIN_CE_LEN;
params.max_ce_len = BLE_GAP_INITIAL_CONN_MAX_CE_LEN;
- rc = ble_gap_conn_update_params(conn->bhc_handle, ¶ms);
+ rc = ble_gap_conn_rx_l2cap_update_req(conn, ¶ms);
+ if (rc == 0) {
+ /* Application agrees to accept parameters; schedule update. */
+ rc = ble_gap_conn_update_params(conn->bhc_handle, ¶ms);
+ if (rc != 0) {
+ return rc;
+ }
+ l2cap_result = BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT;
+ } else {
+ l2cap_result = BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT;
+ }
+
+ /* Send L2CAP response. */
+ rc = ble_l2cap_sig_update_rsp_tx(conn, chan, hdr->identifier,
+ l2cap_result);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static int
+ble_l2cap_sig_update_rsp_rx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct os_mbuf **om)
+{
+ struct ble_l2cap_sig_update_rsp rsp;
+ struct ble_l2cap_sig_proc *proc;
+ struct ble_l2cap_sig_proc *prev;
+ int cb_status;
+ int rc;
+
+ proc = ble_l2cap_sig_proc_find(conn->bhc_handle,
+ BLE_L2CAP_SIG_PROC_OP_UPDATE,
+ hdr->identifier, 1, &prev);
+ if (proc == NULL) {
+ return BLE_HS_ENOENT;
+ }
+
+ if (OS_MBUF_PKTLEN(*om) < BLE_L2CAP_SIG_UPDATE_RSP_SZ) {
+ cb_status = BLE_HS_EBADDATA;
+ rc = BLE_HS_EBADDATA;
+ goto done;
+ }
+
+ *om = os_mbuf_pullup(*om, BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ if (*om == NULL) {
+ cb_status = BLE_HS_ENOMEM;
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ rc = ble_l2cap_sig_update_rsp_parse((*om)->om_data, (*om)->om_len, &rsp);
+ assert(rc == 0);
+
+ switch (rsp.result) {
+ case BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT:
+ cb_status = 0;
+ rc = 0;
+ break;
+
+ case BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT:
+ cb_status = BLE_HS_EREJECT;
+ rc = 0;
+ break;
+
+ default:
+ cb_status = BLE_HS_EBADDATA;
+ rc = BLE_HS_EBADDATA;
+ break;
+ }
+
+done:
+ ble_l2cap_sig_update_call_cb(proc, cb_status);
+ ble_l2cap_sig_proc_remove_free(proc, prev);
+ return rc;
+}
+
+static int
+ble_l2cap_sig_update_kick(struct ble_l2cap_sig_proc *proc)
+{
+ struct ble_l2cap_sig_update_req req;
+ struct ble_l2cap_chan *chan;
+ struct ble_hs_conn *conn;
+ int rc;
+
+ conn = ble_hs_conn_find(proc->conn_handle);
+ if (conn == NULL) {
+ /* Not connected; abort the proedure. */
+ ble_l2cap_sig_update_call_cb(proc, BLE_HS_ENOTCONN);
+ return BLE_HS_EDONE;
+ }
+
+ /* Only the slave can initiate the L2CAP connection update procedure. */
+ if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
+ ble_l2cap_sig_update_call_cb(proc, BLE_HS_EINVAL);
+ return BLE_HS_EDONE;
+ }
+
+ chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_SIG);
+ assert(chan != NULL);
+
+ proc->id = ble_l2cap_sig_next_id();
+ req.itvl_min = proc->update.params.itvl_min;
+ req.itvl_max = proc->update.params.itvl_max;
+ req.slave_latency = proc->update.params.slave_latency;
+ req.timeout_multiplier = proc->update.params.timeout_multiplier;
+
+ rc = ble_l2cap_sig_update_req_tx(conn, chan, proc->id, &req);
if (rc != 0) {
return rc;
}
@@ -283,6 +569,28 @@ ble_l2cap_sig_update_req_rx(struct ble_hs_conn *conn,
return 0;
}
+int
+ble_l2cap_sig_update(uint16_t conn_handle,
+ struct ble_l2cap_sig_update_params *params,
+ ble_l2cap_sig_update_fn *cb, void *cb_arg)
+{
+ struct ble_l2cap_sig_proc *proc;
+ int rc;
+
+ rc = ble_l2cap_sig_new_proc(conn_handle, BLE_L2CAP_SIG_PROC_OP_UPDATE,
+ &proc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ proc->update.params = *params;
+ proc->update.cb = cb;
+ proc->update.cb_arg = cb_arg;
+
+ ble_l2cap_sig_proc_set_pending(proc);
+
+ return 0;
+}
static int
ble_l2cap_sig_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
@@ -290,15 +598,10 @@ ble_l2cap_sig_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
{
ble_l2cap_sig_rx_fn *rx_cb;
struct ble_l2cap_sig_hdr hdr;
- uint8_t u8;
int rc;
- int i;
console_printf("L2CAP - rxed signalling msg: ");
- for (i = 0; i < OS_MBUF_PKTLEN(*om); i++) {
- os_mbuf_copydata(*om, i, 1, &u8);
- console_printf("0x%02x ", u8);
- }
+ ble_hs_misc_log_mbuf(*om);
console_printf("\n");
*om = os_mbuf_pullup(*om, BLE_L2CAP_SIG_HDR_SZ);
@@ -345,3 +648,130 @@ ble_l2cap_sig_create_chan(void)
return chan;
}
+
+/**
+ * Applies periodic checks and actions to all active procedures.
+ *
+ * All procedures that failed due to memory exaustion have their pending flag
+ * set so they can be retried.
+ *
+ * All procedures that have been expecting a response for longer than five
+ * seconds are aborted, and their corresponding connection is terminated.
+ *
+ * Called by the heartbeat timer; executed every second.
+ */
+static void
+ble_l2cap_sig_heartbeat(void *unused)
+{
+ struct ble_l2cap_sig_proc *proc;
+ uint32_t now;
+ int rc;
+
+ now = os_time_get();
+
+ STAILQ_FOREACH(proc, &ble_l2cap_sig_list, next) {
+ if (proc->flags & BLE_L2CAP_SIG_PROC_F_NO_MEM) {
+ proc->flags &= ~BLE_L2CAP_SIG_PROC_F_NO_MEM;
+ if (ble_l2cap_sig_proc_can_pend(proc)) {
+ ble_l2cap_sig_proc_set_pending(proc);
+ }
+ } else if (proc->flags & BLE_L2CAP_SIG_PROC_F_EXPECTING) {
+ if (now - proc->tx_time >= BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT) {
+ rc = ble_gap_conn_terminate(proc->conn_handle);
+ assert(rc == 0); /* XXX */
+ }
+ }
+ }
+
+ rc = os_callout_reset(
+ &ble_l2cap_sig_heartbeat_timer.cf_c,
+ BLE_L2CAP_SIG_HEARTBEAT_PERIOD * OS_TICKS_PER_SEC / 1000);
+ assert(rc == 0);
+}
+
+void
+ble_l2cap_sig_wakeup(void)
+{
+ struct ble_l2cap_sig_proc *proc;
+ struct ble_l2cap_sig_proc *prev;
+ struct ble_l2cap_sig_proc *next;
+ ble_l2cap_sig_kick_fn *kick_cb;
+ int rc;
+
+ prev = NULL;
+ proc = STAILQ_FIRST(&ble_l2cap_sig_list);
+ while (proc != NULL) {
+ next = STAILQ_NEXT(proc, next);
+
+ if (proc->flags & BLE_L2CAP_SIG_PROC_F_PENDING) {
+ kick_cb = ble_l2cap_sig_kick_get(proc->op);
+ rc = kick_cb(proc);
+ switch (rc) {
+ case 0:
+ /* Transmit succeeded. Response expected. */
+ ble_l2cap_sig_proc_set_expecting(proc, prev);
+ /* Current proc got moved to back; old prev still valid. */
+ break;
+
+ case BLE_HS_EAGAIN:
+ /* Transmit failed due to resource shortage. Reschedule. */
+ proc->flags &= ~BLE_L2CAP_SIG_PROC_F_PENDING;
+ /* Current proc remains; reseat prev. */
+ prev = proc;
+ break;
+
+ case BLE_HS_EDONE:
+ /* Procedure complete. */
+ ble_l2cap_sig_proc_remove_free(proc, prev);
+ /* Current proc removed; old prev still valid. */
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+ } else {
+ prev = proc;
+ }
+
+ proc = next;
+ }
+
+ ble_l2cap_sig_assert_sanity();
+}
+
+int
+ble_l2cap_sig_init(void)
+{
+ int rc;
+
+ free(ble_l2cap_sig_proc_mem);
+
+ ble_l2cap_sig_proc_mem = malloc(
+ OS_MEMPOOL_BYTES(BLE_L2CAP_SIG_NUM_PROCS,
+ sizeof (struct ble_l2cap_sig_proc)));
+ if (ble_l2cap_sig_proc_mem == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ rc = os_mempool_init(&ble_l2cap_sig_proc_pool,
+ BLE_L2CAP_SIG_NUM_PROCS,
+ sizeof (struct ble_l2cap_sig_proc),
+ ble_l2cap_sig_proc_mem,
+ "ble_l2cap_sig_proc_pool");
+ if (rc != 0) {
+ goto err;
+ }
+
+ STAILQ_INIT(&ble_l2cap_sig_list);
+
+ os_callout_func_init(&ble_l2cap_sig_heartbeat_timer, &ble_hs_evq,
+ ble_l2cap_sig_heartbeat, NULL);
+
+ return 0;
+
+err:
+ free(ble_l2cap_sig_proc_mem);
+ return rc;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/ble_l2cap_sig_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig_cmd.c b/net/nimble/host/src/ble_l2cap_sig_cmd.c
new file mode 100644
index 0000000..7f62ce0
--- /dev/null
+++ b/net/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -0,0 +1,277 @@
+#include <assert.h>
+#include "ble_hs_priv.h"
+#include "ble_att_priv.h"
+#include "ble_hs_conn.h"
+#include "ble_l2cap_priv.h"
+
+int
+ble_l2cap_sig_hdr_parse(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_L2CAP_SIG_HDR_SZ) {
+ return BLE_HS_EBADDATA;
+ }
+
+ u8ptr = payload;
+ hdr->op = u8ptr[0];
+ hdr->identifier = u8ptr[1];
+ hdr->length = le16toh(u8ptr + 2);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_hdr_write(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_L2CAP_SIG_HDR_SZ) {
+ return BLE_HS_EBADDATA;
+ }
+
+ u8ptr = payload;
+ u8ptr[0] = hdr->op;
+ u8ptr[1] = hdr->identifier;
+ htole16(u8ptr + 2, hdr->length);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_reject_write(void *payload, uint16_t len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_reject *cmd)
+{
+ uint8_t *u8ptr;
+ int rc;
+
+ u8ptr = payload;
+ rc = ble_l2cap_sig_hdr_write(u8ptr, len, hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ u8ptr += BLE_L2CAP_SIG_HDR_SZ;
+ len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ if (len < BLE_L2CAP_SIG_REJECT_MIN_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ htole16(u8ptr, cmd->reason);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
+ uint8_t id, uint16_t reason)
+{
+ /* XXX: Add support for optional data field. */
+
+ struct ble_l2cap_sig_reject cmd;
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *txom;
+ void *v;
+ int rc;
+
+ txom = ble_att_get_pkthdr();
+ if (txom == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ v = os_mbuf_extend(txom,
+ BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_REJECT_MIN_SZ);
+ if (v == NULL) {
+ return BLE_HS_ENOMEM;
+ }
+
+ hdr.op = BLE_L2CAP_SIG_OP_REJECT;
+ hdr.identifier = id;
+ hdr.length = BLE_L2CAP_SIG_REJECT_MIN_SZ;
+ cmd.reason = reason;
+
+ rc = ble_l2cap_sig_reject_write(
+ v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_REJECT_MIN_SZ, &hdr, &cmd);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = ble_l2cap_tx(conn, chan, txom);
+ return rc;
+}
+
+int
+ble_l2cap_sig_update_req_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_req *req)
+{
+ uint8_t *u8ptr;
+
+ if (len < BLE_L2CAP_SIG_UPDATE_REQ_SZ) {
+ return BLE_HS_EBADDATA;
+ }
+
+ u8ptr = payload;
+
+ req->itvl_min = le16toh(u8ptr + 0);
+ req->itvl_max = le16toh(u8ptr + 2);
+ req->slave_latency = le16toh(u8ptr + 4);
+ req->timeout_multiplier = le16toh(u8ptr + 6);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_update_req_write(void *payload, int len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_update_req *req)
+{
+ uint8_t *u8ptr;
+ int rc;
+
+ u8ptr = payload;
+ rc = ble_l2cap_sig_hdr_write(u8ptr, len, hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ u8ptr += BLE_L2CAP_SIG_HDR_SZ;
+ len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ if (len < BLE_L2CAP_SIG_UPDATE_REQ_SZ) {
+ return BLE_HS_EINVAL;
+ }
+
+ htole16(u8ptr + 0, req->itvl_min);
+ htole16(u8ptr + 2, req->itvl_max);
+ htole16(u8ptr + 4, req->slave_latency);
+ htole16(u8ptr + 6, req->timeout_multiplier);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_update_rsp_parse(void *payload, int len,
+ struct ble_l2cap_sig_update_rsp *cmd)
+{
+ uint8_t *u8ptr;
+
+ u8ptr = payload;
+
+ if (len < BLE_L2CAP_SIG_UPDATE_RSP_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ cmd->result = le16toh(u8ptr);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_update_rsp_write(void *payload, int len,
+ struct ble_l2cap_sig_hdr *hdr,
+ struct ble_l2cap_sig_update_rsp *cmd)
+{
+ uint8_t *u8ptr;
+ int rc;
+
+ u8ptr = payload;
+ rc = ble_l2cap_sig_hdr_write(u8ptr, len, hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ u8ptr += BLE_L2CAP_SIG_HDR_SZ;
+ len -= BLE_L2CAP_SIG_HDR_SZ;
+
+ if (len < BLE_L2CAP_SIG_UPDATE_RSP_SZ) {
+ return BLE_HS_EMSGSIZE;
+ }
+
+ htole16(u8ptr, cmd->result);
+
+ return 0;
+}
+
+int
+ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan, uint8_t id,
+ struct ble_l2cap_sig_update_req *req)
+{
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *txom;
+ void *v;
+ int rc;
+
+ txom = ble_att_get_pkthdr();
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ v = os_mbuf_extend(txom,
+ BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
+ if (v == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto done;
+ }
+
+ hdr.op = BLE_L2CAP_SIG_OP_UPDATE_REQ;
+ hdr.identifier = id;
+ hdr.length = BLE_L2CAP_SIG_UPDATE_REQ_SZ;
+
+ rc = ble_l2cap_sig_update_req_write(
+ v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ, &hdr, req);
+ assert(rc == 0);
+
+ rc = ble_l2cap_tx(conn, chan, txom);
+ txom = NULL;
+
+done:
+ os_mbuf_free_chain(txom);
+ return rc;
+}
+
+int
+ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
+ struct ble_l2cap_chan *chan, uint8_t id,
+ uint16_t result)
+{
+ struct ble_l2cap_sig_update_rsp rsp;
+ struct ble_l2cap_sig_hdr hdr;
+ struct os_mbuf *txom;
+ void *v;
+ int rc;
+
+ txom = ble_att_get_pkthdr();
+ if (txom == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ v = os_mbuf_extend(txom,
+ BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+ if (v == NULL) {
+ rc = BLE_HS_ENOMEM;
+ goto err;
+ }
+
+ hdr.op = BLE_L2CAP_SIG_OP_UPDATE_RSP;
+ hdr.identifier = id;
+ hdr.length = BLE_L2CAP_SIG_UPDATE_RSP_SZ;
+ rsp.result = result;
+
+ rc = ble_l2cap_sig_update_rsp_write(
+ v, BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ, &hdr, &rsp);
+ assert(rc == 0);
+
+ rc = ble_l2cap_tx(conn, chan, txom);
+ return rc;
+
+err:
+ os_mbuf_free_chain(txom);
+ return rc;
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/host_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci.c b/net/nimble/host/src/host_hci.c
index 607fb0a..863125f 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -26,7 +26,7 @@
#include "ble_hs_priv.h"
#include "host_dbg.h"
#include "ble_hs_conn.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_hci_ack.h"
#include "ble_gap_priv.h"
#include "ble_hs_adv_priv.h"
@@ -650,19 +650,6 @@ host_hci_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *hdr)
return 0;
}
-static void
-host_hci_log_pkt(struct os_mbuf *om)
-{
- uint8_t u8;
- int i;
-
- for (i = 0; i < OS_MBUF_PKTLEN(om); i++) {
- os_mbuf_copydata(om, i, 1, &u8);
- console_printf("0x%02x ", u8);
- }
- console_printf("\n");
-}
-
/**
* Called when a data packet is received from the controller. This function
* consumes the supplied mbuf, regardless of the outcome.
@@ -689,7 +676,7 @@ host_hci_data_rx(struct os_mbuf *om)
BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
hci_hdr.hdh_len);
- host_hci_log_pkt(om);
+ ble_hs_misc_log_mbuf(om);
if (hci_hdr.hdh_len != OS_MBUF_PKTHDR(om)->omp_len) {
rc = BLE_HS_EMSGSIZE;
@@ -763,7 +750,7 @@ host_hci_data_tx(struct ble_hs_conn *connection, struct os_mbuf *om)
}
console_printf("host_hci_data_tx(): ");
- host_hci_log_pkt(om);
+ ble_hs_misc_log_mbuf(om);
rc = ble_hs_tx_data(om);
if (rc != 0) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
index 99b5660..684b512 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -27,7 +27,7 @@
#include "host_dbg.h"
#include "ble_hci_ack.h"
#include "ble_hs_conn.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#ifdef PHONY_TRANSPORT
#include "host/ble_hs_test.h"
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/test/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c
index da56892..b3de244 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -22,7 +22,7 @@
#include "host/ble_hs_test.h"
#include "host/ble_uuid.h"
#include "testutil/testutil.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_hs_test_util.h"
#include "ble_hs_conn.h"
#include "ble_att_priv.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/test/ble_host_hci_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_host_hci_test.c b/net/nimble/host/src/test/ble_host_hci_test.c
index 284f149..66ce171 100644
--- a/net/nimble/host/src/test/ble_host_hci_test.c
+++ b/net/nimble/host/src/test/ble_host_hci_test.c
@@ -22,7 +22,7 @@
#include "ble_hs_priv.h"
#include "host/ble_hs_test.h"
#include "testutil/testutil.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_hs_conn.h"
#include "ble_att_priv.h"
#include "ble_att_cmd.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/test/ble_hs_adv_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_adv_test.c b/net/nimble/host/src/test/ble_hs_adv_test.c
index 082bd2e..fed7cf2 100644
--- a/net/nimble/host/src/test/ble_hs_adv_test.c
+++ b/net/nimble/host/src/test/ble_hs_adv_test.c
@@ -21,7 +21,7 @@
#include "ble_hs_priv.h"
#include "host/ble_hs_test.h"
#include "host/host_hci.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_priv.h"
#include "ble_hs_conn.h"
#include "ble_hs_adv_priv.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/net/nimble/host/src/test/ble_hs_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_conn_test.c b/net/nimble/host/src/test/ble_hs_conn_test.c
index 504504f..a88e994 100644
--- a/net/nimble/host/src/test/ble_hs_conn_test.c
+++ b/net/nimble/host/src/test/ble_hs_conn_test.c
@@ -21,7 +21,7 @@
#include "ble_hs_priv.h"
#include "host/ble_hs_test.h"
#include "host/host_hci.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_priv.h"
#include "ble_hs_conn.h"
#include "ble_hci_ack.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/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 3ebc521..d46a2e2 100644
--- a/net/nimble/host/src/test/ble_hs_test.c
+++ b/net/nimble/host/src/test/ble_hs_test.c
@@ -19,7 +19,7 @@
#include "ble_hs_priv.h"
#include "host/ble_hs_test.h"
#include "testutil/testutil.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_hs_test_util.h"
void
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/894a15c3/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 68041c4..902653c 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -26,7 +26,7 @@
#include "ble_hci_sched.h"
#include "ble_hs_conn.h"
#include "ble_gap_priv.h"
-#include "ble_l2cap.h"
+#include "ble_l2cap_priv.h"
#include "ble_att_cmd.h"
#include "ble_hs_test_util.h"
@@ -362,6 +362,7 @@ void
ble_hs_test_util_tx_all(void)
{
ble_gattc_wakeup();
+ ble_l2cap_sig_wakeup();
ble_hs_process_tx_data_queue();
}
[3/3] incubator-mynewt-larva git commit: Optimization for processing
of multi-entry rsps.
Posted by cc...@apache.org.
Optimization for processing of multi-entry rsps.
For GATT.
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/c6d01fda
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/c6d01fda
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/c6d01fda
Branch: refs/heads/master
Commit: c6d01fdadb0f9338ed84590c88a2421f98b035fd
Parents: 894a15c
Author: Christopher Collins <cc...@gmail.com>
Authored: Fri Jan 29 14:22:48 2016 -0600
Committer: Christopher Collins <cc...@gmail.com>
Committed: Fri Jan 29 15:56:01 2016 -0800
----------------------------------------------------------------------
net/nimble/host/src/ble_gattc.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/c6d01fda/net/nimble/host/src/ble_gattc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index 4bfaef7..28f5a0d 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -3643,6 +3643,13 @@ ble_gattc_rx_find_info_idata(struct ble_hs_conn *conn,
rc = ble_gattc_disc_all_dscs_rx_idata(proc, conn, idata);
if (rc != 0) {
ble_gattc_proc_remove_free(proc, prev);
+ } else {
+ /* There is probably more data left in the packet. Move this proc to
+ * the front of the list to save us from having to iterate the full
+ * list when the next entry is processed.
+ */
+ ble_gattc_proc_remove(proc, prev);
+ STAILQ_INSERT_HEAD(&ble_gattc_list, proc, next);
}
}
@@ -3696,6 +3703,13 @@ ble_gattc_rx_find_type_value_hinfo(struct ble_hs_conn *conn,
rc = ble_gattc_disc_svc_uuid_rx_hinfo(proc, conn, hinfo);
if (rc != 0) {
ble_gattc_proc_remove_free(proc, prev);
+ } else {
+ /* There is probably more data left in the packet. Move this proc to
+ * the front of the list to save us from having to iterate the full
+ * list when the next entry is processed.
+ */
+ ble_gattc_proc_remove(proc, prev);
+ STAILQ_INSERT_HEAD(&ble_gattc_list, proc, next);
}
}
@@ -3756,6 +3770,13 @@ ble_gattc_rx_read_type_adata(struct ble_hs_conn *conn,
rc = rx_entry->cb(proc, conn, adata);
if (rc != 0) {
ble_gattc_proc_remove_free(proc, prev);
+ } else {
+ /* There is probably more data left in the packet. Move this proc to
+ * the front of the list to save us from having to iterate the full
+ * list when the next entry is processed.
+ */
+ ble_gattc_proc_remove(proc, prev);
+ STAILQ_INSERT_HEAD(&ble_gattc_list, proc, next);
}
}
@@ -3816,6 +3837,13 @@ ble_gattc_rx_read_group_type_adata(struct ble_hs_conn *conn,
rc = ble_gattc_disc_all_svcs_rx_adata(proc, conn, adata);
if (rc != 0) {
ble_gattc_proc_remove_free(proc, prev);
+ } else {
+ /* There is probably more data left in the packet. Move this proc to
+ * the front of the list to save us from having to iterate the full
+ * list when the next entry is processed.
+ */
+ ble_gattc_proc_remove(proc, prev);
+ STAILQ_INSERT_HEAD(&ble_gattc_list, proc, next);
}
}