@@ -67,8 +67,8 @@ struct esp32_bt_gatts_pending_write {
67
67
68
68
struct esp32_bt_gatts_pending_ind {
69
69
uint16_t handle ;
70
+ bool is_ind ;
70
71
struct mg_str value ;
71
- bool need_confirm ;
72
72
STAILQ_ENTRY (esp32_bt_gatts_pending_ind ) next ;
73
73
};
74
74
@@ -107,15 +107,15 @@ static SLIST_HEAD(s_svcs, esp32_bt_gatts_service_entry) s_svcs =
107
107
static SLIST_HEAD (s_conns , esp32_bt_gatts_connection_entry ) s_conns =
108
108
SLIST_HEAD_INITIALIZER (s_conns );
109
109
110
- static void esp32_bt_gatts_send_next_ind (
110
+ static void esp32_bt_gatts_send_next_ind_locked (
111
111
struct esp32_bt_gatts_connection_entry * ce );
112
112
static void esp32_bt_gatts_create_sessions (
113
113
struct esp32_bt_gatts_connection_entry * ce );
114
+ #if 0
114
115
static void esp32_bt_gatts_send_resp (struct mgos_bt_gatts_conn * gsc ,
115
116
uint16_t handle , uint32_t trans_id ,
116
117
enum mgos_bt_gatt_status status );
117
118
118
- #if 0
119
119
esp_gatt_status_t esp32_bt_gatt_get_status (enum mgos_bt_gatt_status st ) {
120
120
switch (st ) {
121
121
case MGOS_BT_GATT_STATUS_OK :
@@ -249,20 +249,19 @@ static void esp32_gatts_register_cb(struct ble_gatt_register_ctxt *ctxt,
249
249
250
250
switch (ctxt -> op ) {
251
251
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" ,
253
253
esp32_bt_uuid_to_str (ctxt -> svc .svc_def -> uuid , buf ),
254
254
ctxt -> svc .handle ));
255
255
break ;
256
256
257
257
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" ,
260
259
esp32_bt_uuid_to_str (ctxt -> chr .chr_def -> uuid , buf ),
261
260
ctxt -> chr .def_handle , ctxt -> chr .val_handle ));
262
261
break ;
263
262
264
263
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" ,
266
265
esp32_bt_uuid_to_str (ctxt -> dsc .dsc_def -> uuid , buf ),
267
266
ctxt -> dsc .handle ));
268
267
break ;
@@ -280,7 +279,6 @@ static struct esp32_bt_gatts_service_entry *find_service_by_uuid(
280
279
}
281
280
return NULL ;
282
281
}
283
- #endif
284
282
285
283
static struct esp32_bt_gatts_service_entry * find_service_by_svc_handle (
286
284
uint16_t svc_handle ) {
@@ -290,6 +288,7 @@ static struct esp32_bt_gatts_service_entry *find_service_by_svc_handle(
290
288
}
291
289
return NULL ;
292
290
}
291
+ #endif
293
292
294
293
static struct esp32_bt_gatts_service_entry * find_service_by_attr_handle (
295
294
uint16_t attr_handle , struct esp32_bt_service_attr_info * * ai ) {
@@ -1108,25 +1107,28 @@ bool mgos_bt_gatts_is_send_queue_empty(void) {
1108
1107
return true;
1109
1108
}
1110
1109
1111
- #if 0
1112
- static void esp32_bt_gatts_send_next_ind (
1110
+ static void esp32_bt_gatts_send_next_ind_locked (
1113
1111
struct esp32_bt_gatts_connection_entry * ce ) {
1112
+ int rc ;
1114
1113
if (ce -> ind_in_flight ) return ;
1115
1114
if (STAILQ_EMPTY (& ce -> pending_inds )) return ;
1116
1115
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 );
1117
1117
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 );
1121
1120
} else {
1121
+ rc = ble_gattc_notify_custom (ce -> gc .conn_id , pi -> handle , om );
1122
+ }
1123
+ if (rc != 0 ) {
1122
1124
ce -> ind_in_flight = false;
1125
+ os_mbuf_free (om );
1123
1126
}
1124
1127
}
1125
- #endif
1126
1128
1127
1129
int esp32_bt_gatts_event (const struct ble_gap_event * ev , void * arg ) {
1128
1130
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 ];
1130
1132
LOG (LL_DEBUG ,
1131
1133
("GATTS EV %d hf %d" , ev -> type , (int ) mgos_get_free_heap_size ()));
1132
1134
mgos_rlock (s_lock );
@@ -1167,18 +1169,17 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
1167
1169
}
1168
1170
struct esp32_bt_gatts_pending_ind * pi , * pit ;
1169
1171
STAILQ_FOREACH_SAFE (pi , & ce -> pending_inds , next , pit ) {
1170
- free (( void * ) pi -> value . p );
1172
+ mg_strfree ( & pi -> value );
1171
1173
memset (pi , 0 , sizeof (* pi ));
1172
1174
free (pi );
1173
1175
}
1174
1176
SLIST_REMOVE (& s_conns , ce , esp32_bt_gatts_connection_entry , next );
1175
1177
free (ce );
1176
1178
break ;
1177
1179
}
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 : {
1181
1181
break ;
1182
+ }
1182
1183
case BLE_GAP_EVENT_MTU : {
1183
1184
struct esp32_bt_gatts_connection_entry * ce =
1184
1185
find_connection (ev -> mtu .conn_handle );
@@ -1195,8 +1196,66 @@ int esp32_bt_gatts_event(const struct ble_gap_event *ev, void *arg) {
1195
1196
}
1196
1197
break ;
1197
1198
}
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 );
1199
1220
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
+ }
1200
1259
}
1201
1260
mgos_runlock (s_lock );
1202
1261
return ret ;
@@ -1461,14 +1520,15 @@ void mgos_bt_gatts_notify(struct mgos_bt_gatts_conn *gsc,
1461
1520
struct esp32_bt_gatts_session_entry * sse = find_session_by_gsc (gsc );
1462
1521
if (sse == NULL ) return ;
1463
1522
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 );
1472
1532
}
1473
1533
1474
1534
void mgos_bt_gatts_notify_uuid (struct mgos_bt_gatts_conn * gsc ,
0 commit comments