Skip to content

Commit b7b61e4

Browse files
nimble/eatt: Implement collision mitigation handling
Introduce operations for collision mitigation handling. Add specification-defined delay for retrying connection.
1 parent d8bd316 commit b7b61e4

File tree

1 file changed

+60
-1
lines changed

1 file changed

+60
-1
lines changed

nimble/host/src/ble_eatt.c

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,13 @@ struct ble_eatt {
4040
uint8_t chan_num;
4141
uint8_t used_channels;
4242
uint8_t accept_channels;
43+
uint8_t collision_ctrl;
44+
uint8_t retry_count;
4345

4446
/* Packet transmit queue */
4547
STAILQ_HEAD(, os_mbuf_pkthdr) eatt_tx_q;
4648

49+
struct os_callout collision_co;
4750
struct ble_npl_event setup_ev;
4851
struct ble_npl_event wakeup_ev;
4952

@@ -199,6 +202,17 @@ ble_eatt_wakeup_cb(struct ble_npl_event *ev)
199202
}
200203
}
201204

205+
static void
206+
ble_eatt_collision_ev(struct os_event *ev)
207+
{
208+
struct os_callout *co = (struct os_callout *)ev;
209+
struct ble_eatt *eatt = CONTAINER_OF(co, struct ble_eatt, collision_co);
210+
211+
if (eatt->retry_count < 2) {
212+
ble_eatt_connect(eatt->conn_handle, eatt->chan_num);
213+
}
214+
}
215+
202216
#if (MYNEWT_VAL(BLE_EATT_AUTO_CONNECT))
203217
void
204218
ble_eatt_auto_conn_cb(struct os_event *ev)
@@ -231,6 +245,9 @@ ble_eatt_alloc(void)
231245

232246
STAILQ_INIT(&eatt->eatt_tx_q);
233247

248+
os_callout_init(&eatt->collision_co, os_eventq_dflt_get(),
249+
ble_eatt_collision_ev, NULL);
250+
234251
#if (MYNEWT_VAL(BLE_EATT_AUTO_CONNECT))
235252
os_callout_init(&eatt->auto_conn_delay, os_eventq_dflt_get(),
236253
ble_eatt_auto_conn_cb, NULL);
@@ -261,6 +278,8 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
261278
struct ble_eatt *eatt = arg;
262279
struct ble_gap_conn_desc desc;
263280
uint8_t free_channels;
281+
uint8_t collision_delay;
282+
uint8_t collision_rand_time;
264283
uint8_t opcode;
265284
int rc;
266285

@@ -271,13 +290,39 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
271290
event->connect.conn_handle, event->connect.chan->scid,
272291
event->connect.chan->dcid, event->connect.status);
273292

293+
if (event->connect.status == BLE_HS_ENOMEM && eatt->collision_ctrl) {
294+
BLE_EATT_LOG_DEBUG("eatt: Connect collision handle: %d\n",
295+
event->connect.conn_handle);
296+
297+
rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
298+
assert(rc == 0);
299+
300+
rc = ble_hs_hci_rand(&collision_rand_time, 1);
301+
if (rc != 0) {
302+
return rc;
303+
}
304+
305+
collision_delay = (collision_rand_time % 5) + 2 * (desc.conn_latency + 1) * desc.conn_itvl;
306+
307+
os_callout_reset(&eatt->collision_co, collision_delay);
308+
309+
eatt->retry_count++;
310+
eatt->used_channels--;
311+
312+
return 0;
313+
}
314+
274315
if (event->connect.status) {
275-
ble_eatt_free(eatt);
316+
eatt->used_channels--;
276317
return 0;
277318
}
278319
eatt->chan = event->connect.chan;
279320
eatt->conn_handle = event->connect.conn_handle;
280321

322+
/* Delete collision callout on successful connection */
323+
os_callout_stop(&eatt->collision_co);
324+
eatt->collision_ctrl = false;
325+
281326
eatt->used_channels++;
282327
BLE_EATT_LOG_DEBUG("eatt: Channels already used for this connection %d\n",
283328
eatt->used_channels);
@@ -319,6 +364,7 @@ ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg)
319364
free_channels = MYNEWT_VAL(BLE_EATT_CHAN_PER_CONN) - ble_eatt_used_channels(eatt->conn_handle);
320365

321366
if (free_channels == 0) {
367+
eatt->collision_ctrl = true;
322368
BLE_EATT_LOG_ERROR("eatt: Accept event | No free channels for "
323369
"conn_handle: %d\n", event->accept.conn_handle);
324370
return BLE_HS_ENOMEM;
@@ -418,6 +464,8 @@ ble_eatt_setup_cb(struct ble_npl_event *ev)
418464

419465
BLE_EATT_LOG_DEBUG("eatt: connecting eatt on conn_handle 0x%04x\n", eatt->conn_handle);
420466

467+
eatt->used_channels += eatt->chan_num;
468+
421469
rc = ble_l2cap_enhanced_connect(eatt->conn_handle, BLE_EATT_PSM,
422470
MYNEWT_VAL(BLE_EATT_MTU),
423471
eatt->chan_num, &om,
@@ -653,7 +701,18 @@ ble_eatt_connect(uint16_t conn_handle, uint8_t chan_num)
653701
}
654702

655703
/*
704+
* 5.3 Vol 3, Part G, Sec. 5.4 L2CAP collision mitigation
705+
* Peripheral shall wait some time before retrying connection.
706+
* Central may reconnect without any delay.
707+
* To reconnect user has to call ble_eatt_connect again.
708+
*/
709+
if (desc.role == BLE_GAP_ROLE_SLAVE && os_callout_queued(&eatt->collision_co)) {
710+
BLE_EATT_LOG_WARN("ble_eatt_connect: Connection collision for handle %d\n",
711+
conn_handle);
656712
return BLE_HS_EALREADY;
713+
}
714+
715+
/*
657716
* Warn about exceeding the number
658717
* of maximum per-conn EATT connections.
659718
*/

0 commit comments

Comments
 (0)