You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2015/12/14 08:00:21 UTC
incubator-mynewt-larva git commit: Add disconnect command and code to
terminate a connection
Repository: incubator-mynewt-larva
Updated Branches:
refs/heads/master 6377a6941 -> 8323f4b76
Add disconnect command and code to terminate a connection
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/8323f4b7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/8323f4b7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/8323f4b7
Branch: refs/heads/master
Commit: 8323f4b76fb8440d8937e0b9401d6dc932afa7b2
Parents: 6377a69
Author: wes3 <wi...@micosa.io>
Authored: Sun Dec 13 23:00:05 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Sun Dec 13 23:00:14 2015 -0800
----------------------------------------------------------------------
.../controller/include/controller/ble_ll.h | 1 +
.../controller/include/controller/ble_ll_conn.h | 23 +-
.../controller/include/controller/ble_ll_ctrl.h | 5 +
.../controller/include/controller/ble_ll_hci.h | 5 +-
net/nimble/controller/src/ble_ll.c | 2 +-
net/nimble/controller/src/ble_ll_conn.c | 273 ++++++++++++++++---
net/nimble/controller/src/ble_ll_ctrl.c | 80 +++++-
net/nimble/controller/src/ble_ll_hci.c | 129 ++++++++-
net/nimble/host/include/host/host_hci.h | 2 +
net/nimble/host/src/ble_hs.c | 2 +-
net/nimble/host/src/host_dbg.c | 29 ++
net/nimble/host/src/host_hci.c | 14 -
net/nimble/host/src/host_hci_cmd.c | 54 +++-
net/nimble/include/nimble/hci_common.h | 7 +
project/bletest/src/main.c | 83 +++++-
15 files changed, 629 insertions(+), 80 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index 64ee545..53782d7 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -296,6 +296,7 @@ uint8_t ble_ll_read_supp_features(void);
#define BLE_LL_LOG_ID_RX_END (2)
#define BLE_LL_LOG_ID_CONN_EV_START (4)
#define BLE_LL_LOG_ID_CONN_EV_END (5)
+#define BLE_LL_LOG_ID_CONN_END (6)
#define BLE_LL_LOG_ID_PHY_SETCHAN (200)
#define BLE_LL_LOG_ID_PHY_DISABLE (201)
#define BLE_LL_LOG_ID_PHY_ISR (202)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index 5236dec..3abc62a 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -20,6 +20,9 @@
#include "os/os.h"
#include "hal/hal_cputime.h"
+/* Connection handle range */
+#define BLE_LL_CONN_MAX_CONN_HANDLE (0x0EFF)
+
/* Channel map size */
#define BLE_LL_CONN_CHMAP_LEN (5)
@@ -86,14 +89,18 @@ struct ble_ll_conn_sm
only use the MD bit now */
/* connection event timing/mgmt */
- uint8_t pdu_txd; /* note: can be 1 bit */
- uint8_t rsp_rxd; /* note: can be 1 bit */
- uint8_t pkt_rxd; /* note: can be 1 bit */
+ uint8_t pdu_txd; /* note: can be 1 bit */
+ uint8_t rsp_rxd; /* note: can be 1 bit */
+ uint8_t pkt_rxd; /* note: can be 1 bit */
+ uint8_t terminate_ind_txd; /* note: can be 1 bit */
+ uint8_t terminate_ind_rxd; /* note: can be 1 bit */
+ uint8_t allow_slave_latency; /* note: can be 1 bit */
+ uint8_t slave_set_last_anchor; /* note: can be 1 bit */
uint8_t master_sca;
uint8_t tx_win_size;
- uint8_t allow_slave_latency; /* note: can be 1 bit */
- uint8_t slave_set_last_anchor; /* note: can be 1 bit */
uint8_t cur_ctrl_proc;
+ uint8_t disconnect_reason;
+ uint8_t rxd_disconnect_reason;
uint16_t pending_ctrl_procs;
uint16_t conn_itvl;
uint16_t slave_latency;
@@ -108,6 +115,7 @@ struct ble_ll_conn_sm
uint32_t anchor_point;
uint32_t last_anchor_point;
uint32_t ce_end_time; /* cputime at which connection event should end */
+ uint32_t terminate_timeout;
uint32_t slave_cur_tx_win_usecs;
uint32_t slave_cur_window_widening;
@@ -142,7 +150,7 @@ struct ble_ll_conn_sm
};
/* API */
-void ble_ll_conn_init(void);
+void ble_ll_conn_module_init(void);
int ble_ll_conn_create(uint8_t *cmdbuf);
int ble_ll_conn_create_cancel(void);
void ble_ll_init_rx_pdu_proc(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr);
@@ -157,9 +165,12 @@ void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status);
+int ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf);
struct ble_ll_len_req;
void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
struct ble_ll_len_req *req);
+struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle);
+
#endif /* H_BLE_LL_CONN_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/include/controller/ble_ll_ctrl.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_ctrl.h b/net/nimble/controller/include/controller/ble_ll_ctrl.h
index 1382f8c..ff47e39 100644
--- a/net/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -34,6 +34,9 @@
#define BLE_LL_CTRL_PROC_NUM (9)
#define BLE_LL_CTRL_PROC_IDLE (255)
+/* Checks if a particular control procedure is running */
+#define IS_PENDING_CTRL_PROC_M(sm, proc) (sm->pending_ctrl_procs & (1 << proc))
+
/*
* LL CTRL PDU format
* -> Opcode (1 byte)
@@ -213,5 +216,7 @@ void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc);
void ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
void ble_ll_ctrl_datalen_chg_event(struct ble_ll_conn_sm *connsm);
void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm);
+void ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm);
+int ble_ll_ctrl_is_terminate_ind(struct os_mbuf *pdu);
#endif /* H_BLE_LL_CTRL_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/include/controller/ble_ll_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_hci.h b/net/nimble/controller/include/controller/ble_ll_hci.h
index 222b772..aa06ee2 100644
--- a/net/nimble/controller/include/controller/ble_ll_hci.h
+++ b/net/nimble/controller/include/controller/ble_ll_hci.h
@@ -35,9 +35,12 @@ void ble_ll_hci_init(void);
/* HCI command processing function */
void ble_ll_hci_cmd_proc(struct os_event *ev);
-/* Used to determine if the LE event is enabled or disabled */
+/* Used to determine if the LE event is enabled/disabled */
uint8_t ble_ll_hci_is_le_event_enabled(int bitpos);
+/* Used to determine if event is enabled/disabled */
+uint8_t ble_ll_hci_is_event_enabled(int bitpos);
+
/* Send event from controller to host */
int ble_ll_hci_event_send(uint8_t *evbuf);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 005d3f7..260056b 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -811,7 +811,7 @@ ble_ll_init(void)
ble_ll_scan_init();
/* Initialize the connection module */
- ble_ll_conn_init();
+ ble_ll_conn_module_init();
/* Set the supported features */
features = 0;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 86c681d..7be491d 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -48,6 +48,14 @@
* We might want to guarantee a IFS time as well since the next event needs
* to be scheduled prior to the start of the event to account for the time it
* takes to get a frame ready (which is pretty much the IFS time).
+ * 7) Do we need to check the terminate timeout inside the connection event?
+ * I think we do.
+ * 8) Use error code 0x3E correctly! Connection failed to establish. If you
+ * read the LE connection complete event, it says that if the connection
+ * fails to be established that the connection complete event gets sent to
+ * the host that issued the create connection.
+ * 9) How does peer address get set if we are using whitelist? Look at filter
+ * policy and make sure you are doing this correctly.
*/
/* XXX: this does not belong here! Move to transport? */
@@ -139,6 +147,7 @@ struct ble_ll_conn_stats
uint32_t conn_ev_late;
uint32_t wfr_expirations;
uint32_t handle_not_found;
+ uint32_t bad_acl_hdr;
uint32_t no_tx_pdu;
uint32_t no_conn_sm;
uint32_t no_free_conn_sm;
@@ -153,6 +162,26 @@ struct ble_ll_conn_stats
struct ble_ll_conn_stats g_ble_ll_conn_stats;
/**
+ * Given a handle, find an active connection matching the handle
+ *
+ * @param handle
+ *
+ * @return struct ble_ll_conn_sm*
+ */
+struct ble_ll_conn_sm *
+ble_ll_conn_find_active_conn(uint16_t handle)
+{
+ struct ble_ll_conn_sm *connsm;
+
+ SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
+ if (connsm->conn_handle == handle) {
+ break;
+ }
+ }
+ return connsm;
+}
+
+/**
* Get a connection state machine.
*/
struct ble_ll_conn_sm *
@@ -460,7 +489,7 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm, int beg_transition)
if (pkthdr) {
m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
nextpkthdr = STAILQ_NEXT(pkthdr, omp_next);
- if (nextpkthdr) {
+ if (nextpkthdr && !connsm->terminate_ind_rxd) {
md = 1;
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
/*
@@ -529,11 +558,18 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm, int beg_transition)
* received a valid frame with the more data bit set to 0 and we dont
* have more data.
*/
- end_transition = BLE_PHY_TRANSITION_TX_RX;
- if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (md == 0) &&
- (connsm->cons_rxd_bad_crc == 0) &&
- ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0)) {
+ if (connsm->terminate_ind_rxd) {
end_transition = BLE_PHY_TRANSITION_NONE;
+ } else {
+ /* XXX: what happens if we are sending a terminate ind? Are we sure
+ we are always going to wait for an ack? */
+ end_transition = BLE_PHY_TRANSITION_TX_RX;
+ if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) && (md == 0) &&
+ (connsm->cons_rxd_bad_crc == 0) &&
+ ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) &&
+ !ble_ll_ctrl_is_terminate_ind(m)) {
+ end_transition = BLE_PHY_TRANSITION_NONE;
+ }
}
rc = ble_phy_tx(m, beg_transition, end_transition);
@@ -827,6 +863,9 @@ ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm)
connsm->event_cntr = 0;
connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
connsm->allow_slave_latency = 0;
+ connsm->disconnect_reason = 0;
+ connsm->terminate_ind_txd = 0;
+ connsm->terminate_ind_rxd = 0;
/* Reset current control procedure */
connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
@@ -923,6 +962,32 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
}
/**
+ * Send a disconnection complete event.
+ *
+ * NOTE: we currently only send this event when we have a reason to send it;
+ * not when it fails.
+ *
+ * @param reason The BLE error code to send as a disconnect reason
+ */
+void
+ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason)
+{
+ uint8_t *evbuf;
+
+ if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DISCONN_CMP - 1)) {
+ evbuf = os_memblock_get(&g_hci_cmd_pool);
+ if (evbuf) {
+ evbuf[0] = BLE_HCI_EVCODE_DISCONN_CMP;
+ evbuf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN;
+ evbuf[2] = BLE_ERR_SUCCESS;
+ htole16(evbuf + 3, connsm->conn_handle);
+ evbuf[5] = reason;
+ ble_ll_hci_event_send(evbuf);
+ }
+ }
+}
+
+/**
* Called when a remotes data length parameters change.
*
* Context: Link Layer task
@@ -1026,14 +1091,31 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
/* Connection state machine is now idle */
connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
+ /* Set current LL connection to NULL */
+ g_ble_ll_conn_cur_sm = NULL;
+
/* Set Link Layer state to standby */
ble_ll_state_set(BLE_LL_STATE_STANDBY);
- /* Send connection complete event */
- ble_ll_conn_comp_event_send(connsm, ble_err);
+ /*
+ * We need to send a disconnection complete event or a connection complete
+ * event when the connection ends. We send a connection complete event
+ * only when we were told to cancel the connection creation.
+ */
+ if (ble_err == BLE_ERR_UNK_CONN_ID) {
+ ble_ll_conn_comp_event_send(connsm, ble_err);
+ } else {
+ ble_ll_disconn_comp_event_send(connsm, ble_err);
+ }
/* Put connection state machine back on free list */
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
+
+ /* Log connection end */
+ ble_ll_log(BLE_LL_LOG_ID_CONN_END,connsm->conn_handle,0,connsm->event_cntr);
+
+ /* turn led off */
+ gpio_set(LED_BLINK_PIN);
}
/**
@@ -1102,6 +1184,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm)
void
ble_ll_conn_event_end(void *arg)
{
+ uint8_t ble_err;
uint16_t latency;
uint32_t itvl;
uint32_t cur_ww;
@@ -1110,6 +1193,21 @@ ble_ll_conn_event_end(void *arg)
connsm = (struct ble_ll_conn_sm *)arg;
+ /* If we have transmitted the terminate IND successfully, we are done */
+ if ((connsm->terminate_ind_txd) || (connsm->terminate_ind_rxd)) {
+ if (connsm->terminate_ind_txd) {
+ ble_err = BLE_ERR_CONN_TERM_LOCAL;
+ } else {
+ /* Make sure the disconnect reason is valid! */
+ ble_err = connsm->rxd_disconnect_reason;
+ if (ble_err == 0) {
+ ble_err = BLE_ERR_REM_USER_CONN_TERM;
+ }
+ }
+ ble_ll_conn_end(connsm, ble_err);
+ return;
+ }
+
/* Disable the PHY */
ble_phy_disable();
@@ -1171,11 +1269,17 @@ ble_ll_conn_event_end(void *arg)
connsm->cons_rxd_bad_crc = 0;
connsm->pkt_rxd = 0;
- /* Link-layer is in standby state now */
- ble_ll_state_set(BLE_LL_STATE_STANDBY);
-
- /* Set current LL connection to NULL */
- g_ble_ll_conn_cur_sm = NULL;
+ /*
+ * If we are trying to terminate connection, check if next wake time is
+ * passed the termination timeout. If so, no need to continue with
+ * connection as we will time out anyway.
+ */
+ if (connsm->pending_ctrl_procs & (1 << BLE_LL_CTRL_PROC_TERMINATE)) {
+ if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) {
+ ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL);
+ return;
+ }
+ }
/* Calculate window widening for next event. If too big, end conn */
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
@@ -1188,6 +1292,12 @@ ble_ll_conn_event_end(void *arg)
connsm->slave_cur_window_widening = cur_ww;
}
+ /* Link-layer is in standby state now */
+ ble_ll_state_set(BLE_LL_STATE_STANDBY);
+
+ /* Set current LL connection to NULL */
+ g_ble_ll_conn_cur_sm = NULL;
+
/* Log event end */
ble_ll_log(BLE_LL_LOG_ID_CONN_EV_END, 0, 0, connsm->event_cntr);
@@ -1904,6 +2014,14 @@ ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint8_t crcok)
if (pkthdr) {
STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next);
txpdu = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
+
+ /* Did we transmit a TERMINATE_IND? If so, we are done */
+ if (ble_ll_ctrl_is_terminate_ind(txpdu)) {
+ connsm->terminate_ind_txd = 1;
+ os_mbuf_free(txpdu);
+ rc = -1;
+ goto conn_event_done;
+ }
os_mbuf_free(txpdu);
} else {
/* No packet on queue? This is an error! */
@@ -1913,7 +2031,12 @@ ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint8_t crcok)
}
/* Should we continue connection event? */
- if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+ /* If this is a TERMINATE_IND, we have to reply */
+ if (ble_ll_ctrl_is_terminate_ind(rxpdu)) {
+ connsm->terminate_ind_rxd = 1;
+ connsm->rxd_disconnect_reason = rxpdu->om_data[3];
+ reply = 1;
+ } else if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
reply = connsm->last_txd_md || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK);
if (reply) {
pkthdr = STAILQ_FIRST(&connsm->conn_txq);
@@ -1939,9 +2062,25 @@ ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint8_t crcok)
/* If reply flag set, send data pdu and continue connection event */
rc = -1;
if (reply) {
+ /*
+ * While this is not perfect, we will just check to see if the
+ * terminate timer will expire within two packet times. If it will,
+ * no use sending the terminate ind. We need to get an ACK for the
+ * terminate ind (master and/or slave) so that is why it is two packets.
+ */
+ if (IS_PENDING_CTRL_PROC_M(connsm, BLE_LL_CTRL_PROC_TERMINATE)) {
+ ticks = ble_ll_pdu_tx_time_get(BLE_LL_PDU_HDR_LEN) +
+ ble_ll_pdu_tx_time_get(BLE_LL_CTRL_TERMINATE_IND_LEN + 3) +
+ BLE_LL_IFS;
+ ticks = cputime_usecs_to_ticks(ticks) + cputime_get32();
+ if ((int32_t)(connsm->terminate_timeout - ticks) < 0) {
+ goto conn_event_done;
+ }
+ }
rc = ble_ll_conn_tx_data_pdu(connsm, BLE_PHY_TRANSITION_RX_TX);
}
+conn_event_done:
if (rc) {
ble_ll_event_send(&connsm->conn_ev_end);
}
@@ -1997,31 +2136,31 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length)
/* See if we have an active matching connection handle */
conn_handle = handle & 0x0FFF;
- SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
- if (connsm->conn_handle == conn_handle) {
- /* Construct LL header in buffer */
- /* XXX: deal with length later */
- assert(length <= 251);
- pb = handle & 0x3000;
- if (pb == 0) {
- om->om_data[0] = BLE_LL_LLID_DATA_START;
- } else if (pb == 0x1000) {
- om->om_data[0] = BLE_LL_LLID_DATA_FRAG;
- } else {
- /* This should never happen! */
- break;
- }
- om->om_data[1] = (uint8_t)length;
-
- /* Clear flags field in BLE header */
- ble_ll_conn_enqueue_pkt(connsm, om);
+ connsm = ble_ll_conn_find_active_conn(conn_handle);
+ if (connsm) {
+ /* Construct LL header in buffer */
+ /* XXX: deal with length later */
+ assert(length <= 251);
+ pb = handle & 0x3000;
+ if (pb == 0) {
+ om->om_data[0] = BLE_LL_LLID_DATA_START;
+ } else if (pb == 0x1000) {
+ om->om_data[0] = BLE_LL_LLID_DATA_FRAG;
+ } else {
+ /* This should never happen! */
+ ++g_ble_ll_conn_stats.bad_acl_hdr;
+ os_mbuf_free(om);
return;
}
- }
+ om->om_data[1] = (uint8_t)length;
- /* No connection found! */
- ++g_ble_ll_conn_stats.handle_not_found;
- os_mbuf_free(om);
+ /* Clear flags field in BLE header */
+ ble_ll_conn_enqueue_pkt(connsm, om);
+ } else {
+ /* No connection found! */
+ ++g_ble_ll_conn_stats.handle_not_found;
+ os_mbuf_free(om);
+ }
}
/**
@@ -2144,9 +2283,71 @@ err_slave_start:
return 0;
}
+/**
+ * Called to process a HCI disconnect command
+ *
+ * Context: Link Layer task (HCI command parser).
+ *
+ * @param cmdbuf
+ *
+ * @return int
+ */
+int
+ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf)
+{
+ int rc;
+ uint8_t reason;
+ uint16_t handle;
+ struct ble_ll_conn_sm *connsm;
+
+ /* Check for valid parameters */
+ handle = le16toh(cmdbuf);
+ reason = cmdbuf[2];
+
+ rc = BLE_ERR_INV_HCI_CMD_PARMS;
+ if (handle <= BLE_LL_CONN_MAX_CONN_HANDLE) {
+ /* Make sure reason is valid */
+ switch (reason) {
+ case BLE_ERR_AUTH_FAIL:
+ case BLE_ERR_REM_USER_CONN_TERM:
+ case BLE_ERR_RD_CONN_TERM_RESRCS:
+ case BLE_ERR_RD_CONN_TERM_PWROFF:
+ case BLE_ERR_UNSUPP_FEATURE:
+ case BLE_ERR_UNIT_KEY_PAIRING:
+ case BLE_ERR_CONN_PARMS:
+ connsm = ble_ll_conn_find_active_conn(handle);
+ if (connsm) {
+ /* Do not allow command if we are in process of disconnecting */
+ if (connsm->disconnect_reason) {
+ rc = BLE_ERR_CMD_DISALLOWED;
+ } else {
+ /* This control procedure better not be pending! */
+ assert(!IS_PENDING_CTRL_PROC_M(connsm,
+ BLE_LL_CTRL_PROC_TERMINATE));
+
+ /* Record the disconnect reason */
+ connsm->disconnect_reason = reason;
+
+ /* Start this control procedure */
+ ble_ll_ctrl_terminate_start(connsm);
+
+ rc = BLE_ERR_SUCCESS;
+ }
+ } else {
+ rc = BLE_ERR_UNK_CONN_ID;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return rc;
+}
+
/* Initialize the connection module */
void
-ble_ll_conn_init(void)
+ble_ll_conn_module_init(void)
{
uint16_t i;
uint16_t maxbytes;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index 73d1727..2ad3772 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -52,10 +52,6 @@
/* XXX: Improvements
* 1) We can inititalize the procedure timer once per connection state machine
*/
-
-/* Checks if a particular control procedure is running */
-#define IS_PENDING_CTRL_PROC_M(sm, proc) (sm->pending_ctrl_procs & (1 << proc))
-
static int
ble_ll_ctrl_chk_supp_bytes(uint16_t bytes)
{
@@ -231,6 +227,11 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
opcode = BLE_LL_CTRL_LENGTH_REQ;
ble_ll_ctrl_datalen_upd_make(connsm, dptr);
break;
+ case BLE_LL_CTRL_PROC_TERMINATE:
+ len = BLE_LL_CTRL_TERMINATE_IND_LEN;
+ opcode = BLE_LL_CTRL_TERMINATE_IND;
+ dptr[3] = connsm->disconnect_reason;
+ break;
default:
assert(0);
break;
@@ -249,6 +250,29 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
}
/**
+ * Called to determine if the pdu is a TERMINATE_IND
+ *
+ * @param pdu
+ *
+ * XXX: should we set a BLE header flag instead to denote TERMINATE_IND?
+ *
+ * @return int 0: not a terminate. 1: yes
+ */
+int
+ble_ll_ctrl_is_terminate_ind(struct os_mbuf *pdu)
+{
+ int rc;
+
+ rc = 0;
+ if ((pdu->om_data[0] & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
+ if (pdu->om_data[BLE_LL_PDU_HDR_LEN] == BLE_LL_CTRL_TERMINATE_IND) {
+ rc = 1;
+ }
+ }
+ return rc;
+}
+
+/**
* Stops the LL control procedure indicated by 'ctrl_proc'.
*
* Context: Link Layer task
@@ -270,9 +294,38 @@ ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc)
}
/**
- * Called to start a LL control procedure. We always set the control
- * procedure pending bit even if the input control procedure has been
- * initiated.
+ * Called to start the terminate procedure.
+ *
+ * Context: Link Layer task.
+ *
+ * @param connsm
+ */
+void
+ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm)
+{
+ int ctrl_proc;
+ uint32_t usecs;
+ struct os_mbuf *om;
+
+ assert(connsm->disconnect_reason != 0);
+
+ ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE;
+ om = ble_ll_ctrl_proc_init(connsm, ctrl_proc);
+ if (om) {
+ ble_ll_conn_enqueue_pkt(connsm, om);
+ connsm->pending_ctrl_procs |= (1 << ctrl_proc);
+
+ /* Set terminate "timeout" */
+ usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000;
+ connsm->terminate_timeout = cputime_get32() +
+ cputime_usecs_to_ticks(usecs);
+ }
+}
+
+/**
+ * Called to start a LL control procedure except for the terminate procedure. We
+ * always set the control procedure pending bit even if the control procedure
+ * has been initiated.
*
* Context: Link Layer task.
*
@@ -283,6 +336,8 @@ ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
{
struct os_mbuf *om;
+ assert(ctrl_proc != BLE_LL_CTRL_PROC_TERMINATE);
+
om = NULL;
if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) {
/* Initiate the control procedure. */
@@ -323,6 +378,17 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
{
int i;
+ /* If we are terminating, dont start any new procedures */
+ if (connsm->disconnect_reason) {
+ /*
+ * If the terminate procedure is not pending it means we were not
+ * able to start it right away (no control pdu was available).
+ * Start it now
+ */
+ ble_ll_ctrl_terminate_start(connsm);
+ return;
+ }
+
/* If there is a running procedure or no pending, do nothing */
if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) &&
(connsm->pending_ctrl_procs != 0)) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c b/net/nimble/controller/src/ble_ll_hci.c
index 9fe7c9e..eff56d8 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -138,9 +138,35 @@ ble_ll_hci_is_le_event_enabled(int bitpos)
uint8_t bytenum;
uint8_t bitmask;
+ /* The LE meta event must be enabled for any LE event to be enabled */
+ enabled = 0;
+ if (g_ble_ll_hci_event_mask[7] & 0x20) {
+ bytenum = bitpos / 8;
+ bitmask = 1 << (bitpos & 0x7);
+ enabled = g_ble_ll_hci_le_event_mask[bytenum] & bitmask;
+ }
+
+ return enabled;
+}
+
+/**
+ * Checks to see if an event has been disabled by the host.
+ *
+ * @param bitpos This is the bit position of the event. Note that this can
+ * be a value from 0 to 63, inclusive.
+ *
+ * @return uint8_t 0: event is not enabled; otherwise event is enabled.
+ */
+uint8_t
+ble_ll_hci_is_event_enabled(int bitpos)
+{
+ uint8_t enabled;
+ uint8_t bytenum;
+ uint8_t bitmask;
+
bytenum = bitpos / 8;
bitmask = 1 << (bitpos & 0x7);
- enabled = g_ble_ll_hci_le_event_mask[bytenum] & bitmask;
+ enabled = g_ble_ll_hci_event_mask[bytenum] & bitmask;
return enabled;
}
@@ -283,6 +309,101 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
return rc;
}
+/**
+ * Process a link control command sent from the host to the controller. The HCI
+ * command has a 3 byte command header followed by data. The header is:
+ * -> opcode (2 bytes)
+ * -> Length of parameters (1 byte; does include command header bytes).
+ *
+ * @param cmdbuf Pointer to command buffer. Points to start of command header.
+ * @param ocf Opcode command field.
+ * @param *rsplen Pointer to length of response
+ *
+ * @return int This function returns a BLE error code. If a command status
+ * event should be returned as opposed to command complete,
+ * 256 gets added to the return value.
+ */
+static int
+ble_ll_hci_link_ctrl_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
+{
+ int rc;
+ uint8_t len;
+ /* XXX: use this? */
+ //uint8_t *rspbuf;
+
+ /* Assume error; if all pass rc gets set to 0 */
+ rc = BLE_ERR_INV_HCI_CMD_PARMS;
+
+ /* Get length from command */
+ len = cmdbuf[sizeof(uint16_t)];
+
+ /*
+ * The command response pointer points into the same buffer as the
+ * command data itself. That is fine, as each command reads all the data
+ * before crafting a response.
+ */
+ /* XXX */
+ //rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
+
+ /* Move past HCI command header */
+ cmdbuf += BLE_HCI_CMD_HDR_LEN;
+
+ switch (ocf) {
+ case BLE_HCI_OCF_DISCONNECT_CMD:
+ if (len == BLE_HCI_DISCONNECT_CMD_LEN) {
+ rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf);
+ }
+ /* Send command status instead of command complete */
+ rc += (BLE_ERR_MAX + 1);
+ break;
+ default:
+ rc = BLE_ERR_UNKNOWN_HCI_CMD;
+ break;
+ }
+
+ return rc;
+}
+
+static int
+ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
+{
+ int rc;
+ uint8_t len;
+ /* XXX: use this? */
+ //uint8_t *rspbuf;
+
+ /* Assume error; if all pass rc gets set to 0 */
+ rc = BLE_ERR_INV_HCI_CMD_PARMS;
+
+ /* Get length from command */
+ len = cmdbuf[sizeof(uint16_t)];
+
+ /*
+ * The command response pointer points into the same buffer as the
+ * command data itself. That is fine, as each command reads all the data
+ * before crafting a response.
+ */
+ /* XXX */
+ //rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
+
+ /* Move past HCI command header */
+ cmdbuf += BLE_HCI_CMD_HDR_LEN;
+
+ switch (ocf) {
+ case BLE_HCI_OCF_CB_SET_EVENT_MASK:
+ if (len == BLE_HCI_SET_EVENT_MASK_LEN) {
+ memcpy(g_ble_ll_hci_event_mask, cmdbuf, len);
+ rc = BLE_ERR_SUCCESS;
+ }
+ break;
+ default:
+ rc = BLE_ERR_UNKNOWN_HCI_CMD;
+ break;
+ }
+
+ return rc;
+}
+
void
ble_ll_hci_cmd_proc(struct os_event *ev)
{
@@ -314,9 +435,11 @@ ble_ll_hci_cmd_proc(struct os_event *ev)
case BLE_HCI_OGF_LE:
rc = ble_ll_hci_le_cmd_proc(cmdbuf, ocf, &rsplen);
break;
+ case BLE_HCI_OGF_LINK_CTRL:
+ rc = ble_ll_hci_link_ctrl_cmd_proc(cmdbuf, ocf, &rsplen);
+ break;
case BLE_HCI_OGF_CTLR_BASEBAND:
- /* XXX: Implement */
- rc = BLE_ERR_UNKNOWN_HCI_CMD;
+ rc = ble_ll_hci_ctlr_bb_cmd_proc(cmdbuf, ocf, &rsplen);
break;
default:
/* XXX: Need to support other OGF. For now, return unsupported */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/host/include/host/host_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/host_hci.h b/net/nimble/host/include/host/host_hci.h
index a8e3d12..c37de90 100644
--- a/net/nimble/host/include/host/host_hci.h
+++ b/net/nimble/host/include/host/host_hci.h
@@ -23,6 +23,8 @@ struct os_mbuf;
int host_hci_os_event_proc(struct os_event *ev);
int host_hci_event_rx(uint8_t *data);
+int host_hci_cmd_set_event_mask(uint64_t event_mask);
+int host_hci_cmd_disconnect(uint16_t handle, uint8_t reason);
int host_hci_cmd_le_set_scan_rsp_data(uint8_t *data, uint8_t len);
int host_hci_cmd_le_set_adv_data(uint8_t *data, uint8_t len);
int host_hci_cmd_le_set_adv_params(struct hci_adv_params *adv);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/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 cc283b1..488bd5e 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -39,7 +39,7 @@
static struct os_task ble_hs_task;
static os_stack_t ble_hs_stack[BLE_HS_STACK_SIZE];
-#define HCI_CMD_BUFS (6)
+#define HCI_CMD_BUFS (8)
#define HCI_CMD_BUF_SIZE (260) /* XXX: temporary, Fix later */
struct os_mempool g_hci_cmd_pool;
static os_membuf_t g_hci_cmd_buf[OS_MEMPOOL_BYTES(HCI_CMD_BUFS,
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/host/src/host_dbg.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_dbg.c b/net/nimble/host/src/host_dbg.c
index 736a719..4c545be 100644
--- a/net/nimble/host/src/host_dbg.c
+++ b/net/nimble/host/src/host_dbg.c
@@ -90,6 +90,32 @@ host_hci_dbg_le_event_disp(uint8_t subev, uint8_t len, uint8_t *evdata)
}
}
+/**
+ * Display a disconnection complete command.
+ *
+ *
+ * @param evdata
+ * @param len
+ */
+void
+host_hci_dbg_disconn_comp_disp(uint8_t *evdata, uint8_t len)
+{
+ uint8_t status;
+ uint8_t reason;
+ uint16_t handle;
+
+ status = evdata[0];
+ handle = le16toh(evdata + 1);
+ /* Ignore reason if status is not success */
+ if (status != BLE_ERR_SUCCESS) {
+ reason = 0;
+ } else {
+ reason = evdata[3];
+ }
+ console_printf("Disconnection Complete: status=%u handle=%u reason=%u\n",
+ status, handle, reason);
+}
+
void
host_hci_dbg_cmd_complete_disp(uint8_t *evdata, uint8_t len)
{
@@ -145,6 +171,9 @@ host_hci_dbg_event_disp(uint8_t *evbuf)
evdata = evbuf + 2;
switch (evcode) {
+ case BLE_HCI_EVCODE_DISCONN_CMP:
+ host_hci_dbg_disconn_comp_disp(evdata, len);
+ break;
case BLE_HCI_EVCODE_COMMAND_COMPLETE:
host_hci_dbg_cmd_complete_disp(evdata, len);
break;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/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 a159468..47f7e64 100644
--- a/net/nimble/host/src/host_hci.c
+++ b/net/nimble/host/src/host_hci.c
@@ -41,20 +41,6 @@ static int host_hci_rx_cmd_status(uint8_t event_code, uint8_t *data, int len);
static int host_hci_rx_le_meta(uint8_t event_code, uint8_t *data, int len);
static int host_hci_rx_le_conn_complete(uint8_t subevent, uint8_t *data,
int len);
-
-#define HCI_CMD_BUFS (8)
-#define HCI_CMD_BUF_SIZE (260) /* XXX: temporary, Fix later */
-struct os_mempool g_hci_cmd_pool;
-os_membuf_t g_hci_cmd_buf[OS_MEMPOOL_SIZE(HCI_CMD_BUFS, HCI_CMD_BUF_SIZE)];
-
-/* XXX: this might be transport layer*/
-#define HCI_NUM_OS_EVENTS (32)
-#define HCI_OS_EVENT_BUF_SIZE (sizeof(struct os_event))
-
-struct os_mempool g_hci_os_event_pool;
-os_membuf_t g_hci_os_event_buf[OS_MEMPOOL_SIZE(HCI_NUM_OS_EVENTS,
- HCI_OS_EVENT_BUF_SIZE)];
-
static uint16_t host_hci_buffer_sz;
static uint8_t host_hci_max_pkts;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/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 8414e77..fc0cf6a 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -29,7 +29,7 @@
#include "ble_l2cap.h"
static int
-host_hci_cmd_send(uint8_t *cmdbuf)
+host_hci_cmd_transport(uint8_t *cmdbuf)
{
#ifdef ARCH_sim
return 0;
@@ -39,7 +39,7 @@ host_hci_cmd_send(uint8_t *cmdbuf)
}
static int
-host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
+host_hci_cmd_send(uint8_t ogf, uint8_t ocf, uint8_t len, void *cmddata)
{
int rc;
uint8_t *cmd;
@@ -51,13 +51,13 @@ host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
rc = -1;
cmd = os_memblock_get(&g_hci_cmd_pool);
if (cmd) {
- opcode = (BLE_HCI_OGF_LE << 10) | ocf;
+ opcode = (ogf << 10) | ocf;
htole16(cmd, opcode);
cmd[2] = len;
if (len) {
memcpy(cmd + BLE_HCI_CMD_HDR_LEN, cmddata, len);
}
- rc = host_hci_cmd_send(cmd);
+ rc = host_hci_cmd_transport(cmd);
if (rc == 0) {
host_hci_outstanding_opcode = opcode;
} else {
@@ -69,6 +69,23 @@ host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
return rc;
}
+/**
+ * Send a LE command from the host to the controller.
+ *
+ * @param ocf
+ * @param len
+ * @param cmddata
+ *
+ * @return int
+ */
+static int
+host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
+{
+ int rc;
+ rc = host_hci_cmd_send(BLE_HCI_OGF_LE, ocf, len, cmddata);
+ return rc;
+}
+
static int
host_hci_cmd_le_whitelist_chg(uint8_t *addr, uint8_t addr_type, uint8_t ocf)
{
@@ -201,6 +218,35 @@ host_hci_cmd_le_set_rand_addr(uint8_t *addr)
}
int
+host_hci_cmd_set_event_mask(uint64_t event_mask)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_SET_EVENT_MASK_LEN];
+
+ htole64(cmd, event_mask);
+ rc = host_hci_cmd_send(BLE_HCI_OGF_CTLR_BASEBAND,
+ BLE_HCI_OCF_CB_SET_EVENT_MASK,
+ BLE_HCI_SET_EVENT_MASK_LEN,
+ cmd);
+ return rc;
+}
+
+int
+host_hci_cmd_disconnect(uint16_t handle, uint8_t reason)
+{
+ int rc;
+ uint8_t cmd[BLE_HCI_DISCONNECT_CMD_LEN];
+
+ htole16(cmd, handle);
+ cmd[2] = reason;
+ rc = host_hci_cmd_send(BLE_HCI_OGF_LINK_CTRL,
+ BLE_HCI_OCF_DISCONNECT_CMD,
+ BLE_HCI_DISCONNECT_CMD_LEN,
+ cmd);
+ return rc;
+}
+
+int
host_hci_cmd_le_set_event_mask(uint64_t event_mask)
{
int rc;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index 6ff1106..f67aa81 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -46,6 +46,13 @@
/* NOTE: 0x07 not defined in specification */
#define BLE_HCI_OGF_LE (0x08)
+/* List of OCF for Link Control commands (OGF=0x01) */
+#define BLE_HCI_OCF_DISCONNECT_CMD (0x0006)
+
+/* Command specific definitions */
+/* Disconnect command */
+#define BLE_HCI_DISCONNECT_CMD_LEN (3)
+
/* List of OCF for Controller and Baseband commands (OGF=0x03) */
#define BLE_HCI_OCF_CB_SET_EVENT_MASK (0x0001)
#define BLE_HCI_OCF_CB_RESET (0x0003)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/8323f4b7/project/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/project/bletest/src/main.c b/project/bletest/src/main.c
index e082257..c492680 100755
--- a/project/bletest/src/main.c
+++ b/project/bletest/src/main.c
@@ -24,9 +24,11 @@
/* BLE */
#include "nimble/ble.h"
+#include "nimble/hci_transport.h"
#include "host/host_hci.h"
#include "host/ble_hs.h"
#include "controller/ble_ll.h"
+#include "controller/ble_ll_conn.h"
/* Init all tasks */
volatile int tasks_initialized;
@@ -62,10 +64,10 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
#define BLETEST_ROLE_ADVERTISER (0)
#define BLETEST_ROLE_SCANNER (1)
#define BLETEST_ROLE_INITIATOR (2)
-#define BLETEST_CFG_ROLE (BLETEST_ROLE_INITIATOR)
+#define BLETEST_CFG_ROLE (BLETEST_ROLE_ADVERTISER)
#define BLETEST_CFG_FILT_DUP_ADV (0)
#define BLETEST_CFG_ADV_ITVL (500000 / BLE_HCI_ADV_ITVL)
-#define BLETEST_CFG_ADV_TYPE BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD
+#define BLETEST_CFG_ADV_TYPE BLE_HCI_ADV_TYPE_ADV_IND
#define BLETEST_CFG_ADV_FILT_POLICY (BLE_HCI_ADV_FILT_NONE)
#define BLETEST_CFG_SCAN_ITVL (700000 / BLE_HCI_SCAN_ITVL)
#define BLETEST_CFG_SCAN_WINDOW (650000 / BLE_HCI_SCAN_ITVL)
@@ -87,6 +89,7 @@ struct os_eventq g_bletest_evq;
struct os_callout_func g_bletest_timer;
struct os_task bletest_task;
os_stack_t bletest_stack[BLETEST_STACK_SIZE];
+uint32_t g_bletest_conn_end;
void
bletest_inc_adv_pkt_num(void)
@@ -288,17 +291,71 @@ bletest_execute(void)
int rc;
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
- /* */
+ int i;
+ uint16_t pktlen;
+ uint16_t handle;
+ struct os_mbuf *om;
+ struct ble_ll_conn_sm *connsm;
+
+ handle = 1;
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
- if (!g_bletest_state) {
+ if (g_bletest_state == 0) {
rc = host_hci_cmd_le_set_adv_enable(1);
host_hci_outstanding_opcode = 0;
assert(rc == 0);
g_bletest_state = 1;
+ } else if (g_bletest_state == 1) {
+ /* See if handle 1 has been created. If so, send packets */
+ connsm = ble_ll_conn_find_active_conn(handle);
+ if (connsm) {
+ /* Set connection end time */
+ g_bletest_conn_end = os_time_get() + (OS_TICKS_PER_SEC * 17);
+ g_bletest_state = 2;
+ }
+ } else if (g_bletest_state == 2) {
+ if ((int32_t)(os_time_get() - g_bletest_conn_end) >= 0) {
+ g_bletest_state = 3;
+ host_hci_cmd_disconnect(handle, BLE_ERR_REM_USER_CONN_TERM);
+ g_next_os_time += OS_TICKS_PER_SEC;
+ return;
+ }
+ ble_get_packet(om);
+ if (om) {
+
+ /* set payload length */
+ pktlen = 32;
+ om->om_len = 32 + 4;
+
+ /* Put the HCI header in the mbuf */
+ htole16(om->om_data, handle);
+ htole16(om->om_data + 2, om->om_len);
+
+ /* Place L2CAP header in packet */
+ htole16(om->om_data + 4, pktlen);
+ om->om_data[6] = 0;
+ om->om_data[7] = 0;
+
+ /* Fill with incrementing pattern */
+ for (i = 0; i < pktlen; ++i) {
+ om->om_data[8 + i] = (uint8_t)(i + 1);
+ }
+
+ /* Add length */
+ om->om_len += 4;
+ OS_MBUF_PKTHDR(om)->omp_len = om->om_len;
+ ble_hci_transport_host_acl_data_send(om);
+ }
+ } else {
+ /* We should be waiting for disconnect */
+ connsm = ble_ll_conn_find_active_conn(handle);
+ if (!connsm) {
+ g_bletest_state = 0;
+ }
}
- g_next_os_time += (OS_TICKS_PER_SEC * 60);
+ g_next_os_time += OS_TICKS_PER_SEC;
}
#endif
+
#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
/* Enable scanning */
if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
@@ -333,7 +390,7 @@ bletest_timer_cb(void *arg)
bletest_execute();
/* Re-start the timer */
- os_callout_reset(&g_bletest_timer.cf_c, OS_TICKS_PER_SEC);
+ os_callout_reset(&g_bletest_timer.cf_c, OS_TICKS_PER_SEC/2);
}
/**
@@ -380,6 +437,15 @@ bletest_task_handler(void *arg)
assert(rc == 0);
host_hci_outstanding_opcode = 0;
+ /* Turn on all events */
+ event_mask = 0xffffffffffffffff;
+ rc = host_hci_cmd_set_event_mask(event_mask);
+ assert(rc == 0);
+ host_hci_outstanding_opcode = 0;
+
+ /* Wait some time before starting */
+ os_time_delay(OS_TICKS_PER_SEC);
+
/* Init bletest variables */
g_bletest_state = 0;
g_next_os_time = os_time_get();
@@ -412,6 +478,8 @@ bletest_task_handler(void *arg)
static int
init_tasks(void)
{
+ int rc;
+
os_task_init(&bletest_task, "bletest", bletest_task_handler, NULL,
BLETEST_TASK_PRIO, OS_WAIT_FOREVER, bletest_stack,
BLETEST_STACK_SIZE);
@@ -419,7 +487,8 @@ init_tasks(void)
tasks_initialized = 1;
/* Initialize host HCI */
- ble_hs_init(HOST_TASK_PRIO);
+ rc = ble_hs_init(HOST_TASK_PRIO);
+ assert(rc == 0);
/* Initialize the BLE LL */
ble_ll_init();