36
36
#include "settings.h"
37
37
#include "gatt_internal.h"
38
38
39
- #define SC_TIMEOUT K_MSEC(10)
39
+ #define SC_TIMEOUT K_MSEC(10)
40
+ #define CCC_STORE_DELAY K_SECONDS(1)
40
41
41
42
/* Persistent storage format for GATT CCC */
42
43
struct ccc_store {
@@ -275,6 +276,59 @@ static void sc_process(struct k_work *work)
275
276
atomic_set_bit (sc -> flags , SC_INDICATE_PENDING );
276
277
}
277
278
279
+ #if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE )
280
+ static struct gatt_ccc_store {
281
+ struct bt_conn * conn_list [CONFIG_BT_MAX_CONN ];
282
+ struct k_delayed_work work ;
283
+ } gatt_ccc_store ;
284
+
285
+ static bool gatt_ccc_conn_is_queued (struct bt_conn * conn )
286
+ {
287
+ return (conn == gatt_ccc_store .conn_list [bt_conn_get_id (conn )]);
288
+ }
289
+
290
+ static void gatt_ccc_conn_unqueue (struct bt_conn * conn )
291
+ {
292
+ u8_t index = bt_conn_get_id (conn );
293
+
294
+ if (gatt_ccc_store .conn_list [index ] != NULL ) {
295
+ bt_conn_unref (gatt_ccc_store .conn_list [index ]);
296
+ gatt_ccc_store .conn_list [index ] = NULL ;
297
+ }
298
+ }
299
+
300
+ static bool gatt_ccc_conn_queue_is_empty (void )
301
+ {
302
+ for (size_t i = 0 ; i < CONFIG_BT_MAX_CONN ; i ++ ) {
303
+ if (gatt_ccc_store .conn_list [i ]) {
304
+ return false;
305
+ }
306
+ }
307
+
308
+ return true;
309
+ }
310
+
311
+ static void ccc_delayed_store (struct k_work * work )
312
+ {
313
+ struct gatt_ccc_store * ccc_store =
314
+ CONTAINER_OF (work , struct gatt_ccc_store , work );
315
+
316
+ for (size_t i = 0 ; i < CONFIG_BT_MAX_CONN ; i ++ ) {
317
+ struct bt_conn * conn = ccc_store -> conn_list [i ];
318
+
319
+ if (!conn ) {
320
+ continue ;
321
+ }
322
+
323
+ if (bt_addr_le_is_bonded (conn -> id , & conn -> le .dst )) {
324
+ bt_gatt_store_ccc (conn -> id , & conn -> le .dst );
325
+ bt_conn_unref (conn );
326
+ ccc_store -> conn_list [i ] = NULL ;
327
+ }
328
+ }
329
+ }
330
+ #endif
331
+
278
332
void bt_gatt_init (void )
279
333
{
280
334
if (!atomic_cas (& init , 0 , 1 )) {
@@ -286,6 +340,9 @@ void bt_gatt_init(void)
286
340
gatt_register (& gatt_svc );
287
341
288
342
k_delayed_work_init (& gatt_sc .work , sc_process );
343
+ #if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE )
344
+ k_delayed_work_init (& gatt_ccc_store .work , ccc_delayed_store );
345
+ #endif
289
346
}
290
347
291
348
static bool update_range (u16_t * start , u16_t * end , u16_t new_start ,
@@ -658,6 +715,19 @@ ssize_t bt_gatt_attr_write_ccc(struct bt_conn *conn,
658
715
/* Update cfg if don't match */
659
716
if (ccc -> cfg [i ].value != ccc -> value ) {
660
717
gatt_ccc_changed (attr , ccc );
718
+
719
+ #if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE )
720
+ if ((!gatt_ccc_conn_is_queued (conn )) &&
721
+ bt_addr_le_is_bonded (conn -> id , & conn -> le .dst )) {
722
+ /* Store the connection with the same index it has in
723
+ * the conns array
724
+ */
725
+ gatt_ccc_store .conn_list [bt_conn_get_id (conn )] =
726
+ bt_conn_ref (conn );
727
+ k_delayed_work_submit (& gatt_ccc_store .work ,
728
+ CCC_STORE_DELAY );
729
+ }
730
+ #endif
661
731
}
662
732
663
733
/* Disabled CCC is the same as no configured CCC, so clear the entry */
@@ -2365,6 +2435,14 @@ void bt_gatt_disconnected(struct bt_conn *conn)
2365
2435
BT_DBG ("conn %p" , conn );
2366
2436
bt_gatt_foreach_attr (0x0001 , 0xffff , disconnected_cb , conn );
2367
2437
2438
+ #if defined(CONFIG_BT_SETTINGS_CCC_STORE_ON_WRITE )
2439
+ gatt_ccc_conn_unqueue (conn );
2440
+
2441
+ if (gatt_ccc_conn_queue_is_empty ()) {
2442
+ k_delayed_work_cancel (& gatt_ccc_store .work );
2443
+ }
2444
+ #endif
2445
+
2368
2446
if (IS_ENABLED (CONFIG_BT_SETTINGS ) &&
2369
2447
bt_addr_le_is_bonded (conn -> id , & conn -> le .dst )) {
2370
2448
bt_gatt_store_ccc (conn -> id , & conn -> le .dst );
0 commit comments