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:19 UTC
[2/3] incubator-mynewt-larva git commit: L2CAP signal channel.
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();
}