Skip to content

Commit 8b009c8

Browse files
committed
Notifications/indications support
1 parent 022e026 commit 8b009c8

File tree

3 files changed

+92
-30
lines changed

3 files changed

+92
-30
lines changed

src/esp32/esp32_bt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ bool mgos_bt_common_init(void) {
260260
// and services registered.
261261
mgos_invoke_cb(esp32_bt_start, NULL, false /* from_isr */);
262262

263+
// Default INFO level log is too spammy.
264+
esp_log_level_set("NimBLE", ESP_LOG_WARN);
265+
263266
LOG(LL_INFO, ("Bluetooth init ok, MTU %d, pairing %s, %d paired devices",
264267
mgos_sys_config_get_bt_gatt_mtu(),
265268
(mgos_bt_gap_get_pairing_enable() ? "enabled" : "disabled"),

src/esp32/esp32_bt_gap.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,10 @@ static int esp32_bt_gap_event(struct ble_gap_event *ev, void *arg) {
181181
mgos_bt_gap_set_adv_enable(mgos_bt_gap_get_adv_enable());
182182
// fallthrough
183183
case BLE_GAP_EVENT_DISCONNECT:
184-
case BLE_GAP_EVENT_CONN_UPDATE:
185184
case BLE_GAP_EVENT_ENC_CHANGE:
186185
case BLE_GAP_EVENT_SUBSCRIBE:
187-
case BLE_GAP_EVENT_MTU:
188186
case BLE_GAP_EVENT_NOTIFY_TX:
187+
case BLE_GAP_EVENT_MTU:
189188
esp32_bt_gatts_event(ev, arg);
190189
break;
191190
case BLE_GAP_EVENT_ADV_COMPLETE:

src/esp32/esp32_bt_gatts.c

Lines changed: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ struct esp32_bt_gatts_pending_write {
6767

6868
struct esp32_bt_gatts_pending_ind {
6969
uint16_t handle;
70+
bool is_ind;
7071
struct mg_str value;
71-
bool need_confirm;
7272
STAILQ_ENTRY(esp32_bt_gatts_pending_ind) next;
7373
};
7474

@@ -107,15 +107,15 @@ static SLIST_HEAD(s_svcs, esp32_bt_gatts_service_entry) s_svcs =
107107
static SLIST_HEAD(s_conns, esp32_bt_gatts_connection_entry) s_conns =
108108
SLIST_HEAD_INITIALIZER(s_conns);
109109

110-
static void esp32_bt_gatts_send_next_ind(
110+
static void esp32_bt_gatts_send_next_ind_locked(
111111
struct esp32_bt_gatts_connection_entry *ce);
112112
static void esp32_bt_gatts_create_sessions(
113113
struct esp32_bt_gatts_connection_entry *ce);
114+
#if 0
114115
static void esp32_bt_gatts_send_resp(struct mgos_bt_gatts_conn *gsc,
115116
uint16_t handle, uint32_t trans_id,
116117
enum mgos_bt_gatt_status status);
117118

118-
#if 0
119119
esp_gatt_status_t esp32_bt_gatt_get_status(enum mgos_bt_gatt_status st) {
120120
switch (st) {
121121
case MGOS_BT_GATT_STATUS_OK:
@@ -249,20 +249,19 @@ static void esp32_gatts_register_cb(struct ble_gatt_register_ctxt *ctxt,
249249

250250
switch (ctxt->op) {
251251
case BLE_GATT_REGISTER_OP_SVC:
252-
LOG(LL_DEBUG, ("Registering service %s with handle=%d",
252+
LOG(LL_DEBUG, ("REGISTER_OP_SVC %s sh %d",
253253
esp32_bt_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
254254
ctxt->svc.handle));
255255
break;
256256

257257
case BLE_GATT_REGISTER_OP_CHR:
258-
LOG(LL_DEBUG, ("Registering characteristic %s with "
259-
"def_handle=%d val_handle=%d",
258+
LOG(LL_DEBUG, ("REGISTER_OP_CHR %s dh %d vh %d",
260259
esp32_bt_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
261260
ctxt->chr.def_handle, ctxt->chr.val_handle));
262261
break;
263262

264263
case BLE_GATT_REGISTER_OP_DSC:
265-
LOG(LL_DEBUG, ("Registering descriptor %s with handle=%d",
264+
LOG(LL_DEBUG, ("REGISTER_OP_DSC %s vh %d",
266265
esp32_bt_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
267266
ctxt->dsc.handle));
268267
break;
@@ -280,7 +279,6 @@ static struct esp32_bt_gatts_service_entry *find_service_by_uuid(
280279
}
281280
return NULL;
282281
}
283-
#endif
284282

285283
static struct esp32_bt_gatts_service_entry *find_service_by_svc_handle(
286284
uint16_t svc_handle) {
@@ -290,6 +288,7 @@ static struct esp32_bt_gatts_service_entry *find_service_by_svc_handle(
290288
}
291289
return NULL;
292290
}
291+
#endif
293292

294293
static struct esp32_bt_gatts_service_entry *find_service_by_attr_handle(
295294
uint16_t attr_handle, struct esp32_bt_service_attr_info **ai) {
@@ -1108,25 +1107,28 @@ bool mgos_bt_gatts_is_send_queue_empty(void) {
11081107
return true;
11091108
}
11101109

1111-
#if 0
1112-
static void esp32_bt_gatts_send_next_ind(
1110+
static void esp32_bt_gatts_send_next_ind_locked(
11131111
struct esp32_bt_gatts_connection_entry *ce) {
1112+
int rc;
11141113
if (ce->ind_in_flight) return;
11151114
if (STAILQ_EMPTY(&ce->pending_inds)) return;
11161115
struct esp32_bt_gatts_pending_ind *pi = STAILQ_FIRST(&ce->pending_inds);
1116+
struct os_mbuf *om = ble_hs_mbuf_from_flat(pi->value.p, pi->value.len);
11171117
ce->ind_in_flight = true;
1118-
if (esp_ble_gatts_send_indicate(ce->gatt_if, ce->gc.conn_id, pi->handle,
1119-
pi->value.len, (uint8_t *) pi->value.p,
1120-
pi->need_confirm) == ESP_OK) {
1118+
if (pi->is_ind) {
1119+
rc = ble_gattc_indicate_custom(ce->gc.conn_id, pi->handle, om);
11211120
} else {
1121+
rc = ble_gattc_notify_custom(ce->gc.conn_id, pi->handle, om);
1122+
}
1123+
if (rc != 0) {
11221124
ce->ind_in_flight = false;
1125+
os_mbuf_free(om);
11231126
}
11241127
}
1125-
#endif
11261128

11271129
int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
11281130
int ret = 0;
1129-
char a1[MGOS_BT_ADDR_STR_LEN];
1131+
char a1[MGOS_BT_UUID_STR_LEN], a2[MGOS_BT_UUID_STR_LEN];
11301132
LOG(LL_DEBUG,
11311133
("GATTS EV %d hf %d", ev->type, (int) mgos_get_free_heap_size()));
11321134
mgos_rlock(s_lock);
@@ -1167,18 +1169,17 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
11671169
}
11681170
struct esp32_bt_gatts_pending_ind *pi, *pit;
11691171
STAILQ_FOREACH_SAFE(pi, &ce->pending_inds, next, pit) {
1170-
free((void *) pi->value.p);
1172+
mg_strfree(&pi->value);
11711173
memset(pi, 0, sizeof(*pi));
11721174
free(pi);
11731175
}
11741176
SLIST_REMOVE(&s_conns, ce, esp32_bt_gatts_connection_entry, next);
11751177
free(ce);
11761178
break;
11771179
}
1178-
case BLE_GAP_EVENT_CONN_UPDATE:
1179-
case BLE_GAP_EVENT_ENC_CHANGE:
1180-
case BLE_GAP_EVENT_SUBSCRIBE:
1180+
case BLE_GAP_EVENT_ENC_CHANGE: {
11811181
break;
1182+
}
11821183
case BLE_GAP_EVENT_MTU: {
11831184
struct esp32_bt_gatts_connection_entry *ce =
11841185
find_connection(ev->mtu.conn_handle);
@@ -1195,8 +1196,66 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
11951196
}
11961197
break;
11971198
}
1198-
case BLE_GAP_EVENT_NOTIFY_TX:
1199+
case BLE_GAP_EVENT_SUBSCRIBE: {
1200+
uint16_t ch = ev->subscribe.conn_handle;
1201+
uint16_t ah = ev->subscribe.attr_handle;
1202+
struct esp32_bt_service_attr_info *ai = NULL;
1203+
struct esp32_bt_gatts_session_entry *sse = find_session(ch, ah, &ai);
1204+
if (sse == NULL) break;
1205+
struct mgos_bt_gatts_notify_mode_arg narg = {
1206+
.svc_uuid = sse->se->uuid,
1207+
.char_uuid = ai->def.uuid_bin,
1208+
.handle = ev->subscribe.attr_handle,
1209+
.mode = MGOS_BT_GATT_NOTIFY_MODE_OFF,
1210+
};
1211+
if (ev->subscribe.cur_notify) {
1212+
narg.mode = MGOS_BT_GATT_NOTIFY_MODE_NOTIFY;
1213+
} else if (ev->subscribe.cur_indicate) {
1214+
narg.mode = MGOS_BT_GATT_NOTIFY_MODE_INDICATE;
1215+
}
1216+
LOG(LL_DEBUG, ("NOTIFY_MODE c %d h %d %s/%s %d", ch, ah,
1217+
mgos_bt_uuid_to_str(&narg.svc_uuid, a1),
1218+
mgos_bt_uuid_to_str(&narg.char_uuid, a2), narg.mode));
1219+
esp32_bt_gatts_call_handler(sse, ai, MGOS_BT_GATTS_EV_NOTIFY_MODE, &narg);
11991220
break;
1221+
}
1222+
case BLE_GAP_EVENT_NOTIFY_TX: {
1223+
uint16_t ch = ev->notify_tx.conn_handle;
1224+
uint16_t ah = ev->notify_tx.attr_handle;
1225+
struct esp32_bt_service_attr_info *ai = NULL;
1226+
struct esp32_bt_gatts_session_entry *sse = find_session(ch, ah, &ai);
1227+
if (sse == NULL) break;
1228+
struct esp32_bt_gatts_connection_entry *ce = sse->ce;
1229+
ce->ind_in_flight = false;
1230+
LOG(LL_DEBUG,
1231+
("NOTIFY_TX ch %d ah %d st %d", ch, ah, ev->notify_tx.status));
1232+
if (STAILQ_EMPTY(&ce->pending_inds)) break; // Shouldn't happen.
1233+
bool remove = false;
1234+
struct esp32_bt_gatts_pending_ind *pi = STAILQ_FIRST(&ce->pending_inds);
1235+
if (pi->is_ind) {
1236+
// Indication raises this event twice: first with status 0 when
1237+
// indication is sent, then again when it is acknowledged or times out.
1238+
if (ev->notify_tx.status == 0) break;
1239+
remove = (ev->notify_tx.status == BLE_HS_EDONE);
1240+
struct mgos_bt_gatts_ind_confirm_arg ic_arg = {
1241+
.handle = pi->handle,
1242+
.ok = remove,
1243+
};
1244+
esp32_bt_gatts_call_handler(sse, ai, MGOS_BT_GATTS_EV_IND_CONFIRM,
1245+
&ic_arg);
1246+
} else {
1247+
remove = (ev->notify_tx.status == 0);
1248+
}
1249+
if (remove) {
1250+
STAILQ_REMOVE_HEAD(&ce->pending_inds, next);
1251+
mg_strfree(&pi->value);
1252+
ce->ind_queue_len--;
1253+
free(pi);
1254+
}
1255+
// Send next one or retry sending this one that failed.
1256+
esp32_bt_gatts_send_next_ind_locked(ce);
1257+
break;
1258+
}
12001259
}
12011260
mgos_runlock(s_lock);
12021261
return ret;
@@ -1461,14 +1520,15 @@ void mgos_bt_gatts_notify(struct mgos_bt_gatts_conn *gsc,
14611520
struct esp32_bt_gatts_session_entry *sse = find_session_by_gsc(gsc);
14621521
if (sse == NULL) return;
14631522
struct esp32_bt_gatts_pending_ind *pi = calloc(1, sizeof(*pi));
1464-
if (pi != NULL) {
1465-
pi->handle = handle;
1466-
pi->need_confirm = (mode == MGOS_BT_GATT_NOTIFY_MODE_INDICATE);
1467-
pi->value = mg_strdup(data);
1468-
STAILQ_INSERT_TAIL(&sse->ce->pending_inds, pi, next);
1469-
sse->ce->ind_queue_len++;
1470-
}
1471-
// esp32_bt_gatts_send_next_ind(sse->ce);
1523+
if (pi == NULL) return;
1524+
pi->handle = handle;
1525+
pi->is_ind = (mode == MGOS_BT_GATT_NOTIFY_MODE_INDICATE);
1526+
pi->value = mg_strdup(data);
1527+
mgos_rlock(s_lock);
1528+
STAILQ_INSERT_TAIL(&sse->ce->pending_inds, pi, next);
1529+
sse->ce->ind_queue_len++;
1530+
esp32_bt_gatts_send_next_ind_locked(sse->ce);
1531+
mgos_runlock(s_lock);
14721532
}
14731533

14741534
void mgos_bt_gatts_notify_uuid(struct mgos_bt_gatts_conn *gsc,

0 commit comments

Comments
 (0)