diff --git a/pkg/nimble/netif/include/nimble_netif_conn.h b/pkg/nimble/netif/include/nimble_netif_conn.h index 423bbd3651be..02ad46d42f0a 100644 --- a/pkg/nimble/netif/include/nimble_netif_conn.h +++ b/pkg/nimble/netif/include/nimble_netif_conn.h @@ -42,6 +42,7 @@ extern "C" { typedef struct { struct ble_l2cap_chan *coc; /**< l2cap context as exposed by NimBLE */ uint16_t gaphandle; /**< GAP handle exposed by NimBLE */ + uint16_t itvl; /**< currently used connection interval */ uint16_t state; /**< the current state of the context */ uint8_t addr[BLE_ADDR_LEN]; /**< BLE address of connected peer (in network byte order) */ @@ -181,10 +182,10 @@ void nimble_netif_conn_free(int handle, uint8_t *addr); * * @param[in] handle connection handle * - * @return used connection interval on success, multiples of 1.25ms + * @return used connection interval in milliseconds on success * @return 0 if unable to get connection interval */ -uint16_t nimble_netif_conn_get_itvl(int handle); +uint16_t nimble_netif_conn_get_itvl_ms(int handle); /** * @brief Check if the given connection interval is used, taking the minimal @@ -200,17 +201,6 @@ uint16_t nimble_netif_conn_get_itvl(int handle); */ bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle); -/** - * @brief Check if connection interval used by the given connection is valid - * - * @param[in] handle connection to verify - * - * @return true if the connection interval of the given connection collides - * with the connection interval of another BLE connection - * @return false if the connection interval of the given connection is valid - */ -bool nimble_netif_conn_itvl_invalid(int handle); - /** * @brief Generate a pseudorandom connection interval from the given range * diff --git a/pkg/nimble/netif/nimble_netif.c b/pkg/nimble/netif/nimble_netif.c index d991ced593dd..0a2b70a82a15 100644 --- a/pkg/nimble/netif/nimble_netif.c +++ b/pkg/nimble/netif/nimble_netif.c @@ -364,20 +364,32 @@ static int _on_l2cap_server_evt(struct ble_l2cap_event *event, void *arg) conn = nimble_netif_conn_get(handle); assert(conn); + /* in the unlikely event the L2CAP connection establishment fails, + * we close the GAP connection */ if (event->connect.status != 0) { - /* in the unlikely event the L2CAP connection establishment - * fails, we close the GAP connection */ ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM); break; } + + /* we need to update the state to keep everything in sync */ conn->coc = event->connect.chan; conn->state |= NIMBLE_NETIF_L2CAP_SERVER; conn->state &= ~(NIMBLE_NETIF_ADV | NIMBLE_NETIF_CONNECTING); + + /* in case conn itvl spacing is enabled, make sure that the conn + * itvl of the new connection is sufficiently spaced */ + if ((NIMBLE_NETIF_CONN_ITVL_SPACING > 0) && + nimble_netif_conn_itvl_used(conn->itvl, handle)) { + ble_gap_terminate(conn->gaphandle, BLE_ERR_REM_USER_CONN_TERM); + break; + } + _notify(handle, NIMBLE_NETIF_CONNECTED_SLAVE, conn->addr); break; case BLE_L2CAP_EVENT_COC_DISCONNECTED: conn = nimble_netif_conn_from_gaphandle(event->disconnect.conn_handle); assert(conn && (conn->state & NIMBLE_NETIF_L2CAP_SERVER)); + conn->coc = NULL; conn->state &= ~NIMBLE_NETIF_L2CAP_CONNECTED; break; case BLE_L2CAP_EVENT_COC_ACCEPT: { @@ -411,9 +423,21 @@ static void _on_gap_connected(nimble_netif_conn_t *conn, uint16_t conn_handle) (void)res; conn->gaphandle = conn_handle; + conn->itvl = desc.conn_itvl; bluetil_addr_swapped_cp(desc.peer_id_addr.val, conn->addr); } +static void _on_gap_param_update(int handle, nimble_netif_conn_t *conn) +{ + struct ble_gap_conn_desc desc; + int res = ble_gap_conn_find(conn->gaphandle, &desc); + assert(res == 0) ; + (void)res; + + conn->itvl = desc.conn_itvl; + _notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr); +} + static int _on_gap_master_evt(struct ble_gap_event *event, void *arg) { int res = 0; @@ -458,7 +482,7 @@ static int _on_gap_master_evt(struct ble_gap_event *event, void *arg) break; } case BLE_GAP_EVENT_CONN_UPDATE: - _notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr); + _on_gap_param_update(handle, conn); break; case BLE_GAP_EVENT_CONN_UPDATE_REQ: case BLE_GAP_EVENT_MTU: @@ -485,11 +509,6 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg) _notify(handle, NIMBLE_NETIF_ABORT_SLAVE, addr); break; } - if ((NIMBLE_NETIF_CONN_ITVL_SPACING > 0) && - nimble_netif_conn_itvl_invalid(handle)) { - nimble_netif_close(handle); - break; - } _on_gap_connected(conn, event->connect.conn_handle); assert(conn->state == NIMBLE_NETIF_ADV); conn->state = NIMBLE_NETIF_GAP_SLAVE; @@ -507,7 +526,7 @@ static int _on_gap_slave_evt(struct ble_gap_event *event, void *arg) break; } case BLE_GAP_EVENT_CONN_UPDATE: - _notify(handle, NIMBLE_NETIF_CONN_UPDATED, conn->addr); + _on_gap_param_update(handle, conn); break; case BLE_GAP_EVENT_CONN_UPDATE_REQ: /* nothing to do here */ diff --git a/pkg/nimble/netif/nimble_netif_conn.c b/pkg/nimble/netif/nimble_netif_conn.c index 87f48f281b2e..25f27acb61c5 100644 --- a/pkg/nimble/netif/nimble_netif_conn.c +++ b/pkg/nimble/netif/nimble_netif_conn.c @@ -222,33 +222,24 @@ unsigned nimble_netif_conn_count(uint16_t filter) return cnt; } -uint16_t nimble_netif_conn_get_itvl(int handle) +uint16_t nimble_netif_conn_get_itvl_ms(int handle) { - assert((handle >= 0) && (handle < CONN_CNT)); - struct ble_gap_conn_desc desc; - - if (!(_conn[handle].state & NIMBLE_NETIF_GAP_CONNECTED)) { - return 0; - } - int res = ble_gap_conn_find(_conn[handle].gaphandle, &desc); - if (res != 0) { + if ((handle == 0) || (handle >= CONN_CNT)) { return 0; } - return desc.conn_itvl; + return ((_conn[handle].itvl * BLE_HCI_CONN_ITVL) / 1000); } bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle) { - for (unsigned i = 0; i < CONN_CNT; i++) { - if (i != skip_handle) { - uint16_t conn_itvl = nimble_netif_conn_get_itvl(i); - if (conn_itvl != 0) { - uint16_t diff = (conn_itvl < itvl) ? itvl - conn_itvl - : conn_itvl - itvl; - if (diff < NIMBLE_NETIF_CONN_ITVL_SPACING) { - return true; - } + for (int handle = 0; handle < CONN_CNT; handle++) { + if ((handle != skip_handle) && (_conn[handle].itvl != 0)) { + uint16_t diff = (_conn[handle].itvl < itvl) + ? itvl - _conn[handle].itvl + : _conn[handle].itvl - itvl; + if (diff < NIMBLE_NETIF_CONN_ITVL_SPACING) { + return true; } } } @@ -256,19 +247,6 @@ bool nimble_netif_conn_itvl_used(uint16_t itvl, int skip_handle) return false; } -bool nimble_netif_conn_itvl_invalid(int handle) -{ - if (NIMBLE_NETIF_CONN_ITVL_SPACING == 0) { - return false; - } - - uint16_t to_check = nimble_netif_conn_get_itvl(handle); - if (to_check == 0) { - return false; - } - return nimble_netif_conn_itvl_used(to_check, handle); -} - uint16_t nimble_netif_conn_gen_itvl(uint16_t min, uint16_t max) { assert(min <= max);