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 <w...@micosa.io> Authored: Sun Dec 13 23:00:05 2015 -0800 Committer: wes3 <w...@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();