xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_gatts_notify_test.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <string.h>
21 #include <errno.h>
22 #include "testutil/testutil.h"
23 #include "nimble/ble.h"
24 #include "host/ble_uuid.h"
25 #include "host/ble_hs_test.h"
26 #include "ble_hs_test_util.h"
27 
28 #define BLE_GATTS_NOTIFY_TEST_CHR_1_UUID    0x1111
29 #define BLE_GATTS_NOTIFY_TEST_CHR_2_UUID    0x2222
30 
31 #define BLE_GATTS_NOTIFY_TEST_MAX_EVENTS    16
32 
33 static uint8_t ble_gatts_notify_test_peer_addr[6] = {2,3,4,5,6,7};
34 
35 static int
36 ble_gatts_notify_test_misc_access(uint16_t conn_handle,
37                                   uint16_t attr_handle,
38                                   struct ble_gatt_access_ctxt *ctxt,
39                                   void *arg);
40 static void
41 ble_gatts_notify_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
42                                   void *arg);
43 
44 static const struct ble_gatt_svc_def ble_gatts_notify_test_svcs[] = { {
45     .type = BLE_GATT_SVC_TYPE_PRIMARY,
46     .uuid = BLE_UUID16_DECLARE(0x1234),
47     .characteristics = (struct ble_gatt_chr_def[]) { {
48         .uuid = BLE_UUID16_DECLARE(BLE_GATTS_NOTIFY_TEST_CHR_1_UUID),
49         .access_cb = ble_gatts_notify_test_misc_access,
50         .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
51                  BLE_GATT_CHR_F_INDICATE,
52     }, {
53         .uuid = BLE_UUID16_DECLARE(BLE_GATTS_NOTIFY_TEST_CHR_2_UUID),
54         .access_cb = ble_gatts_notify_test_misc_access,
55         .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
56                  BLE_GATT_CHR_F_INDICATE,
57     }, {
58         0
59     } },
60 }, {
61     0
62 } };
63 
64 static uint16_t ble_gatts_notify_test_chr_1_def_handle;
65 static uint8_t ble_gatts_notify_test_chr_1_val[1024];
66 static int ble_gatts_notify_test_chr_1_len;
67 static uint16_t ble_gatts_notify_test_chr_2_def_handle;
68 static uint8_t ble_gatts_notify_test_chr_2_val[1024];
69 static int ble_gatts_notify_test_chr_2_len;
70 
71 static struct ble_gap_event
72 ble_gatts_notify_test_events[BLE_GATTS_NOTIFY_TEST_MAX_EVENTS];
73 
74 static int ble_gatts_notify_test_num_events;
75 
76 typedef int ble_store_write_fn(int obj_type, const union ble_store_value *val);
77 
78 typedef int ble_store_delete_fn(int obj_type, const union ble_store_key *key);
79 
80 static int
ble_gatts_notify_test_util_gap_event(struct ble_gap_event * event,void * arg)81 ble_gatts_notify_test_util_gap_event(struct ble_gap_event *event, void *arg)
82 {
83     switch (event->type) {
84     case BLE_GAP_EVENT_NOTIFY_TX:
85     case BLE_GAP_EVENT_SUBSCRIBE:
86         TEST_ASSERT_FATAL(ble_gatts_notify_test_num_events <
87                           BLE_GATTS_NOTIFY_TEST_MAX_EVENTS);
88 
89         ble_gatts_notify_test_events[ble_gatts_notify_test_num_events++] =
90             *event;
91 
92     default:
93         break;
94     }
95 
96     return 0;
97 }
98 
99 static uint16_t
ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,uint16_t chr_def_handle)100 ble_gatts_notify_test_misc_read_notify(uint16_t conn_handle,
101                                        uint16_t chr_def_handle)
102 {
103     struct ble_att_read_req req;
104     struct os_mbuf *om;
105     uint8_t buf[BLE_ATT_READ_REQ_SZ];
106     uint16_t flags;
107     int rc;
108 
109     req.barq_handle = chr_def_handle + 2;
110     ble_att_read_req_write(buf, sizeof buf, &req);
111 
112     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
113                                                 buf, sizeof buf);
114     TEST_ASSERT(rc == 0);
115 
116     om = ble_hs_test_util_prev_tx_dequeue_pullup();
117     TEST_ASSERT_FATAL(om != NULL);
118     TEST_ASSERT_FATAL(om->om_len == 3);
119     TEST_ASSERT_FATAL(om->om_data[0] == BLE_ATT_OP_READ_RSP);
120 
121     flags = get_le16(om->om_data + 1);
122     return flags;
123 }
124 
125 static void
ble_gatts_notify_test_misc_try_enable_notify(uint16_t conn_handle,uint16_t chr_def_handle,uint16_t flags,int fail)126 ble_gatts_notify_test_misc_try_enable_notify(uint16_t conn_handle,
127                                              uint16_t chr_def_handle,
128                                              uint16_t flags, int fail)
129 {
130     struct ble_att_write_req req;
131     uint8_t buf[BLE_ATT_WRITE_REQ_BASE_SZ + 2];
132     int rc;
133 
134     req.bawq_handle = chr_def_handle + 2;
135     ble_att_write_req_write(buf, sizeof buf, &req);
136 
137     put_le16(buf + BLE_ATT_WRITE_REQ_BASE_SZ, flags);
138     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
139                                                 buf, sizeof buf);
140     if (fail) {
141         TEST_ASSERT_FATAL(rc != 0);
142         ble_hs_test_util_verify_tx_err_rsp(BLE_ATT_OP_WRITE_REQ,
143                                            req.bawq_handle,
144                                            BLE_ATT_ERR_REQ_NOT_SUPPORTED);
145     } else {
146         TEST_ASSERT_FATAL(rc == 0);
147         ble_hs_test_util_verify_tx_write_rsp();
148     }
149 }
150 
151 static void
ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,uint16_t chr_def_handle,uint16_t flags)152 ble_gatts_notify_test_misc_enable_notify(uint16_t conn_handle,
153                                          uint16_t chr_def_handle,
154                                          uint16_t flags)
155 {
156     ble_gatts_notify_test_misc_try_enable_notify(conn_handle,
157                                                  chr_def_handle,
158                                                  flags, 0);
159 }
160 
161 static void
ble_gatts_notify_test_util_next_event(struct ble_gap_event * event)162 ble_gatts_notify_test_util_next_event(struct ble_gap_event *event)
163 {
164     TEST_ASSERT_FATAL(ble_gatts_notify_test_num_events > 0);
165 
166     *event = *ble_gatts_notify_test_events;
167 
168     ble_gatts_notify_test_num_events--;
169     if (ble_gatts_notify_test_num_events > 0) {
170         memmove(ble_gatts_notify_test_events + 0,
171                 ble_gatts_notify_test_events + 1,
172                 ble_gatts_notify_test_num_events * sizeof *event);
173     }
174 }
175 
176 static void
ble_gatts_notify_test_util_verify_sub_event(uint16_t conn_handle,uint8_t attr_handle,uint8_t reason,uint8_t prevn,uint8_t curn,uint8_t previ,uint8_t curi)177 ble_gatts_notify_test_util_verify_sub_event(uint16_t conn_handle,
178                                             uint8_t attr_handle,
179                                             uint8_t reason,
180                                             uint8_t prevn, uint8_t curn,
181                                             uint8_t previ, uint8_t curi)
182 {
183     struct ble_gap_event event;
184 
185     ble_gatts_notify_test_util_next_event(&event);
186 
187     TEST_ASSERT(event.type == BLE_GAP_EVENT_SUBSCRIBE);
188     TEST_ASSERT(event.subscribe.conn_handle == conn_handle);
189     TEST_ASSERT(event.subscribe.attr_handle == attr_handle);
190     TEST_ASSERT(event.subscribe.reason == reason);
191     TEST_ASSERT(event.subscribe.prev_notify == prevn);
192     TEST_ASSERT(event.subscribe.cur_notify == curn);
193     TEST_ASSERT(event.subscribe.prev_indicate == previ);
194     TEST_ASSERT(event.subscribe.cur_indicate == curi);
195 }
196 
197 static void
ble_gatts_notify_test_util_verify_tx_event(uint16_t conn_handle,uint8_t attr_handle,int status,int indication)198 ble_gatts_notify_test_util_verify_tx_event(uint16_t conn_handle,
199                                            uint8_t attr_handle,
200                                            int status,
201                                            int indication)
202 {
203     struct ble_gap_event event;
204 
205     ble_gatts_notify_test_util_next_event(&event);
206 
207     TEST_ASSERT(event.type == BLE_GAP_EVENT_NOTIFY_TX);
208     TEST_ASSERT(event.notify_tx.status == status);
209     TEST_ASSERT(event.notify_tx.conn_handle == conn_handle);
210     TEST_ASSERT(event.notify_tx.attr_handle == attr_handle);
211     TEST_ASSERT(event.notify_tx.indication == indication);
212 }
213 
214 static void
ble_gatts_notify_test_util_verify_ack_event(uint16_t conn_handle,uint8_t attr_handle)215 ble_gatts_notify_test_util_verify_ack_event(uint16_t conn_handle,
216                                             uint8_t attr_handle)
217 {
218     ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle,
219                                                BLE_HS_EDONE, 1);
220 }
221 
222 static void
ble_gatts_notify_test_misc_init(uint16_t * out_conn_handle,int bonding,uint16_t chr1_flags,uint16_t chr2_flags)223 ble_gatts_notify_test_misc_init(uint16_t *out_conn_handle, int bonding,
224                                 uint16_t chr1_flags, uint16_t chr2_flags)
225 {
226     struct ble_hs_conn *conn;
227     uint16_t flags;
228     int exp_num_cccds;
229 
230     ble_hs_test_util_init();
231     ble_gatts_notify_test_num_events = 0;
232 
233     ble_hs_test_util_reg_svcs(ble_gatts_notify_test_svcs,
234                               ble_gatts_notify_test_misc_reg_cb,
235                               NULL);
236     TEST_ASSERT_FATAL(ble_gatts_notify_test_chr_1_def_handle != 0);
237     TEST_ASSERT_FATAL(ble_gatts_notify_test_chr_2_def_handle != 0);
238 
239     ble_hs_test_util_create_conn(2, ble_gatts_notify_test_peer_addr,
240                                  ble_gatts_notify_test_util_gap_event, NULL);
241     *out_conn_handle = 2;
242 
243     if (bonding) {
244         ble_hs_lock();
245         conn = ble_hs_conn_find(2);
246         TEST_ASSERT_FATAL(conn != NULL);
247         conn->bhc_sec_state.encrypted = 1;
248         conn->bhc_sec_state.authenticated = 1;
249         conn->bhc_sec_state.bonded = 1;
250         ble_hs_unlock();
251     }
252 
253     /* Ensure notifications disabled on new connection. */
254     flags = ble_gatts_notify_test_misc_read_notify(
255         2, ble_gatts_notify_test_chr_1_def_handle);
256     TEST_ASSERT(flags == 0);
257     flags = ble_gatts_notify_test_misc_read_notify(
258         2, ble_gatts_notify_test_chr_2_def_handle);
259     TEST_ASSERT(flags == 0);
260 
261     /* Set initial notification / indication state and verify that subscription
262      * callback gets executed.
263      */
264     if (chr1_flags != 0) {
265         ble_gatts_notify_test_misc_enable_notify(
266             2, ble_gatts_notify_test_chr_1_def_handle, chr1_flags);
267 
268         ble_gatts_notify_test_util_verify_sub_event(
269             *out_conn_handle,
270             ble_gatts_notify_test_chr_1_def_handle + 1,
271             BLE_GAP_SUBSCRIBE_REASON_WRITE,
272             0, chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
273             0, chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
274     }
275     if (chr2_flags != 0) {
276         ble_gatts_notify_test_misc_enable_notify(
277             2, ble_gatts_notify_test_chr_2_def_handle, chr2_flags);
278 
279         ble_gatts_notify_test_util_verify_sub_event(
280             *out_conn_handle,
281             ble_gatts_notify_test_chr_2_def_handle + 1,
282             BLE_GAP_SUBSCRIBE_REASON_WRITE,
283             0, chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
284             0, chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
285     }
286 
287     /* Ensure no extraneous subscription callbacks were executed. */
288     TEST_ASSERT(ble_gatts_notify_test_num_events == 0);
289 
290     /* Toss both write responses. */
291     ble_hs_test_util_prev_tx_queue_clear();
292 
293     /* Ensure notification / indication state reads back correctly. */
294     flags = ble_gatts_notify_test_misc_read_notify(
295         2, ble_gatts_notify_test_chr_1_def_handle);
296     TEST_ASSERT(flags == chr1_flags);
297     flags = ble_gatts_notify_test_misc_read_notify(
298         2, ble_gatts_notify_test_chr_2_def_handle);
299     TEST_ASSERT(flags == chr2_flags);
300 
301     /* Ensure both CCCDs still persisted. */
302     if (bonding) {
303         exp_num_cccds = (chr1_flags != 0) + (chr2_flags != 0);
304     } else {
305         exp_num_cccds = 0;
306     }
307     TEST_ASSERT(ble_hs_test_util_num_cccds() == exp_num_cccds);
308 }
309 
310 static void
ble_gatts_notify_test_disconnect(uint16_t conn_handle,uint8_t chr1_flags,uint8_t chr1_indicate_in_progress,uint8_t chr2_flags,uint8_t chr2_indicate_in_progress)311 ble_gatts_notify_test_disconnect(uint16_t conn_handle,
312                                  uint8_t chr1_flags,
313                                  uint8_t chr1_indicate_in_progress,
314                                  uint8_t chr2_flags,
315                                  uint8_t chr2_indicate_in_progress)
316 {
317     ble_hs_test_util_conn_disconnect(conn_handle);
318 
319     if (chr1_indicate_in_progress) {
320         ble_gatts_notify_test_util_verify_tx_event(
321             conn_handle,
322             ble_gatts_notify_test_chr_1_def_handle + 1,
323             BLE_HS_ENOTCONN,
324             1);
325     }
326 
327     /* Verify subscription callback executed for each subscribed
328      * characteristic.
329      */
330     if (chr1_flags != 0) {
331         ble_gatts_notify_test_util_verify_sub_event(
332             conn_handle,
333             ble_gatts_notify_test_chr_1_def_handle + 1,
334             BLE_GAP_SUBSCRIBE_REASON_TERM,
335             chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
336             chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE, 0);
337     }
338 
339     if (chr2_indicate_in_progress) {
340         ble_gatts_notify_test_util_verify_tx_event(
341             conn_handle,
342             ble_gatts_notify_test_chr_2_def_handle + 1,
343             BLE_HS_ENOTCONN,
344             1);
345     }
346 
347     if (chr2_flags != 0) {
348         ble_gatts_notify_test_util_verify_sub_event(
349             conn_handle,
350             ble_gatts_notify_test_chr_2_def_handle + 1,
351             BLE_GAP_SUBSCRIBE_REASON_TERM,
352             chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
353             chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE, 0);
354     }
355 }
356 
357 static void
ble_gatts_notify_test_misc_reg_cb(struct ble_gatt_register_ctxt * ctxt,void * arg)358 ble_gatts_notify_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
359                                   void *arg)
360 {
361     uint16_t uuid16;
362 
363     if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) {
364         uuid16 = ble_uuid_u16(ctxt->chr.chr_def->uuid);
365         switch (uuid16) {
366         case BLE_GATTS_NOTIFY_TEST_CHR_1_UUID:
367             ble_gatts_notify_test_chr_1_def_handle = ctxt->chr.def_handle;
368             break;
369 
370         case BLE_GATTS_NOTIFY_TEST_CHR_2_UUID:
371             ble_gatts_notify_test_chr_2_def_handle = ctxt->chr.def_handle;
372             break;
373 
374         default:
375             TEST_ASSERT_FATAL(0);
376             break;
377         }
378     }
379 }
380 
381 static int
ble_gatts_notify_test_misc_access(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)382 ble_gatts_notify_test_misc_access(uint16_t conn_handle,
383                                   uint16_t attr_handle,
384                                   struct ble_gatt_access_ctxt *ctxt,
385                                   void *arg)
386 {
387     int rc;
388 
389     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
390     TEST_ASSERT(conn_handle == 0xffff);
391 
392     if (attr_handle == ble_gatts_notify_test_chr_1_def_handle + 1) {
393         TEST_ASSERT(ctxt->chr ==
394                     &ble_gatts_notify_test_svcs[0].characteristics[0]);
395         rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_1_val,
396                               ble_gatts_notify_test_chr_1_len);
397         TEST_ASSERT_FATAL(rc == 0);
398     } else if (attr_handle == ble_gatts_notify_test_chr_2_def_handle + 1) {
399         TEST_ASSERT(ctxt->chr ==
400                     &ble_gatts_notify_test_svcs[0].characteristics[1]);
401         rc = os_mbuf_copyinto(ctxt->om, 0, ble_gatts_notify_test_chr_2_val,
402                               ble_gatts_notify_test_chr_2_len);
403         TEST_ASSERT_FATAL(rc == 0);
404     } else {
405         TEST_ASSERT_FATAL(0);
406     }
407 
408     return 0;
409 }
410 
411 static void
ble_gatts_notify_test_misc_rx_indicate_rsp(uint16_t conn_handle,uint16_t attr_handle)412 ble_gatts_notify_test_misc_rx_indicate_rsp(uint16_t conn_handle,
413                                            uint16_t attr_handle)
414 {
415     uint8_t buf[BLE_ATT_INDICATE_RSP_SZ];
416     int rc;
417 
418     ble_att_indicate_rsp_write(buf, sizeof buf);
419 
420     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
421                                                 buf, sizeof buf);
422     TEST_ASSERT(rc == 0);
423 
424     ble_gatts_notify_test_util_verify_ack_event(conn_handle, attr_handle);
425 }
426 
427 static void
ble_gatts_notify_test_misc_verify_tx_n(uint16_t conn_handle,uint16_t attr_handle,const uint8_t * attr_data,int attr_len)428 ble_gatts_notify_test_misc_verify_tx_n(uint16_t conn_handle,
429                                        uint16_t attr_handle,
430                                        const uint8_t *attr_data, int attr_len)
431 {
432     struct ble_att_notify_req req;
433     struct os_mbuf *om;
434     int i;
435 
436     om = ble_hs_test_util_prev_tx_dequeue_pullup();
437     TEST_ASSERT_FATAL(om != NULL);
438 
439     ble_att_notify_req_parse(om->om_data, om->om_len, &req);
440     TEST_ASSERT(req.banq_handle == attr_handle);
441 
442     for (i = 0; i < attr_len; i++) {
443         TEST_ASSERT(om->om_data[BLE_ATT_NOTIFY_REQ_BASE_SZ + i] ==
444                     attr_data[i]);
445     }
446 
447     ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle, 0, 0);
448 }
449 
450 static void
ble_gatts_notify_test_misc_verify_tx_i(uint16_t conn_handle,uint16_t attr_handle,const uint8_t * attr_data,int attr_len)451 ble_gatts_notify_test_misc_verify_tx_i(uint16_t conn_handle,
452                                        uint16_t attr_handle,
453                                        const uint8_t *attr_data, int attr_len)
454 {
455     struct ble_att_indicate_req req;
456     struct os_mbuf *om;
457     int i;
458 
459     om = ble_hs_test_util_prev_tx_dequeue_pullup();
460     TEST_ASSERT_FATAL(om != NULL);
461 
462     ble_att_indicate_req_parse(om->om_data, om->om_len, &req);
463     TEST_ASSERT(req.baiq_handle == attr_handle);
464 
465     for (i = 0; i < attr_len; i++) {
466         TEST_ASSERT(om->om_data[BLE_ATT_INDICATE_REQ_BASE_SZ + i] ==
467                     attr_data[i]);
468     }
469 
470     ble_gatts_notify_test_util_verify_tx_event(conn_handle, attr_handle, 0, 1);
471 }
472 
473 static void
ble_gatts_notify_test_misc_verify_tx_gen(uint16_t conn_handle,int attr_idx,uint8_t chr_flags)474 ble_gatts_notify_test_misc_verify_tx_gen(uint16_t conn_handle, int attr_idx,
475                                          uint8_t chr_flags)
476 {
477     uint16_t attr_handle;
478     uint16_t attr_len;
479     void *attr_val;
480 
481     switch (attr_idx) {
482     case 1:
483         attr_handle = ble_gatts_notify_test_chr_1_def_handle + 1;
484         attr_len = ble_gatts_notify_test_chr_1_len;
485         attr_val = ble_gatts_notify_test_chr_1_val;
486         break;
487 
488     case 2:
489         attr_handle = ble_gatts_notify_test_chr_2_def_handle + 1;
490         attr_len = ble_gatts_notify_test_chr_2_len;
491         attr_val = ble_gatts_notify_test_chr_2_val;
492         break;
493 
494     default:
495         TEST_ASSERT_FATAL(0);
496         break;
497     }
498 
499     switch (chr_flags) {
500     case 0:
501         break;
502 
503     case BLE_GATTS_CLT_CFG_F_NOTIFY:
504         ble_gatts_notify_test_misc_verify_tx_n(conn_handle, attr_handle,
505                                                attr_val, attr_len);
506         break;
507 
508     case BLE_GATTS_CLT_CFG_F_INDICATE:
509         ble_gatts_notify_test_misc_verify_tx_i(conn_handle, attr_handle,
510                                                attr_val, attr_len);
511         break;
512 
513     default:
514         TEST_ASSERT_FATAL(0);
515         break;
516     }
517 }
518 
519 static void
ble_gatts_notify_test_restore_bonding(uint16_t conn_handle,uint8_t chr1_flags,uint8_t chr1_tx,uint8_t chr2_flags,uint8_t chr2_tx)520 ble_gatts_notify_test_restore_bonding(uint16_t conn_handle,
521                                       uint8_t chr1_flags, uint8_t chr1_tx,
522                                       uint8_t chr2_flags, uint8_t chr2_tx)
523 {
524     struct ble_hs_conn *conn;
525 
526     ble_hs_lock();
527     conn = ble_hs_conn_find(conn_handle);
528     TEST_ASSERT_FATAL(conn != NULL);
529     conn->bhc_sec_state.encrypted = 1;
530     conn->bhc_sec_state.authenticated = 1;
531     conn->bhc_sec_state.bonded = 1;
532     ble_hs_unlock();
533 
534     ble_gatts_bonding_restored(conn_handle);
535 
536     /* Verify subscription callback executed for each subscribed
537      * characteristic.
538      */
539     if (chr1_flags != 0) {
540         ble_gatts_notify_test_util_verify_sub_event(
541             conn_handle,
542             ble_gatts_notify_test_chr_1_def_handle + 1,
543             BLE_GAP_SUBSCRIBE_REASON_RESTORE,
544             0, chr1_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
545             0, chr1_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
546 
547     }
548     if (chr1_tx) {
549         ble_gatts_notify_test_misc_verify_tx_gen(conn_handle, 1, chr1_flags);
550     }
551 
552     if (chr2_flags != 0) {
553         ble_gatts_notify_test_util_verify_sub_event(
554             conn_handle,
555             ble_gatts_notify_test_chr_2_def_handle + 1,
556             BLE_GAP_SUBSCRIBE_REASON_RESTORE,
557             0, chr2_flags == BLE_GATTS_CLT_CFG_F_NOTIFY,
558             0, chr2_flags == BLE_GATTS_CLT_CFG_F_INDICATE);
559     }
560     if (chr2_tx) {
561         ble_gatts_notify_test_misc_verify_tx_gen(conn_handle, 2, chr2_flags);
562     }
563 }
564 
TEST_CASE(ble_gatts_notify_test_n)565 TEST_CASE(ble_gatts_notify_test_n)
566 {
567     static const uint8_t fourbytes[] = { 1, 2, 3, 4 };
568     struct os_mbuf *om;
569     uint16_t conn_handle;
570     uint16_t flags;
571     int rc;
572 
573     ble_gatts_notify_test_misc_init(&conn_handle, 0,
574                                     BLE_GATTS_CLT_CFG_F_NOTIFY,
575                                     BLE_GATTS_CLT_CFG_F_NOTIFY);
576 
577     /* Ensure notifications read back as enabled. */
578     flags = ble_gatts_notify_test_misc_read_notify(
579         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
580     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
581     flags = ble_gatts_notify_test_misc_read_notify(
582         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
583     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
584 
585     /* Verify custom notification data. */
586     om = ble_hs_mbuf_from_flat(fourbytes, sizeof fourbytes);
587     TEST_ASSERT_FATAL(om != NULL);
588 
589     rc = ble_gattc_notify_custom(conn_handle,
590                                  ble_gatts_notify_test_chr_1_def_handle + 1,
591                                  om);
592     TEST_ASSERT_FATAL(rc == 0);
593 
594     ble_gatts_notify_test_misc_verify_tx_n(
595         conn_handle,
596         ble_gatts_notify_test_chr_1_def_handle + 1,
597         fourbytes,
598         sizeof fourbytes);
599 
600     /* Update characteristic 1's value. */
601     ble_gatts_notify_test_chr_1_len = 1;
602     ble_gatts_notify_test_chr_1_val[0] = 0xab;
603     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
604 
605     /* Verify notification sent properly. */
606     ble_gatts_notify_test_misc_verify_tx_n(
607         conn_handle,
608         ble_gatts_notify_test_chr_1_def_handle + 1,
609         ble_gatts_notify_test_chr_1_val,
610         ble_gatts_notify_test_chr_1_len);
611 
612     /* Update characteristic 2's value. */
613     ble_gatts_notify_test_chr_2_len = 16;
614     memcpy(ble_gatts_notify_test_chr_2_val,
615            ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
616     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
617 
618     /* Verify notification sent properly. */
619     ble_gatts_notify_test_misc_verify_tx_n(
620         conn_handle,
621         ble_gatts_notify_test_chr_2_def_handle + 1,
622         ble_gatts_notify_test_chr_2_val,
623         ble_gatts_notify_test_chr_2_len);
624 
625     /***
626      * Disconnect, modify characteristic values, and reconnect.  Ensure
627      * notifications are not sent and are no longer enabled.
628      */
629 
630     ble_gatts_notify_test_disconnect(conn_handle,
631                                      BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
632                                      BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
633 
634     /* Update characteristic 1's value. */
635     ble_gatts_notify_test_chr_1_len = 1;
636     ble_gatts_notify_test_chr_1_val[0] = 0xdd;
637     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
638 
639     /* Update characteristic 2's value. */
640     ble_gatts_notify_test_chr_2_len = 16;
641     memcpy(ble_gatts_notify_test_chr_2_val,
642            ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
643     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
644 
645     ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
646                                  ble_gatts_notify_test_util_gap_event, NULL);
647 
648     /* Ensure no notifications sent. */
649     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
650 
651     /* Ensure notifications disabled. */
652     flags = ble_gatts_notify_test_misc_read_notify(
653         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
654     TEST_ASSERT(flags == 0);
655     flags = ble_gatts_notify_test_misc_read_notify(
656         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
657     TEST_ASSERT(flags == 0);
658 }
659 
TEST_CASE(ble_gatts_notify_test_i)660 TEST_CASE(ble_gatts_notify_test_i)
661 {
662     static const uint8_t fourbytes[] = { 1, 2, 3, 4 };
663     struct os_mbuf *om;
664     uint16_t conn_handle;
665     uint16_t flags;
666     int rc;
667 
668     ble_gatts_notify_test_misc_init(&conn_handle, 0,
669                                     BLE_GATTS_CLT_CFG_F_INDICATE,
670                                     BLE_GATTS_CLT_CFG_F_INDICATE);
671 
672     /* Verify custom indication data. */
673     om = ble_hs_mbuf_from_flat(fourbytes, sizeof fourbytes);
674     TEST_ASSERT_FATAL(om != NULL);
675 
676     rc = ble_gattc_indicate_custom(conn_handle,
677                                    ble_gatts_notify_test_chr_1_def_handle + 1,
678                                    om);
679     TEST_ASSERT_FATAL(rc == 0);
680 
681     ble_gatts_notify_test_misc_verify_tx_i(
682         conn_handle,
683         ble_gatts_notify_test_chr_1_def_handle + 1,
684         fourbytes,
685         sizeof fourbytes);
686 
687     /* Receive the confirmation for the indication. */
688     ble_gatts_notify_test_misc_rx_indicate_rsp(
689         conn_handle,
690         ble_gatts_notify_test_chr_1_def_handle + 1);
691 
692     /* Update characteristic 1's value. */
693     ble_gatts_notify_test_chr_1_len = 1;
694     ble_gatts_notify_test_chr_1_val[0] = 0xab;
695     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
696 
697     /* Verify indication sent properly. */
698     ble_gatts_notify_test_misc_verify_tx_i(
699         conn_handle,
700         ble_gatts_notify_test_chr_1_def_handle + 1,
701         ble_gatts_notify_test_chr_1_val,
702         ble_gatts_notify_test_chr_1_len);
703 
704     /* Update characteristic 2's value. */
705     ble_gatts_notify_test_chr_2_len = 16;
706     memcpy(ble_gatts_notify_test_chr_2_val,
707            ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
708     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
709 
710     /* Verify the second indication doesn't get sent until the first is
711      * confirmed.
712      */
713     TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
714 
715     /* Receive the confirmation for the first indication. */
716     ble_gatts_notify_test_misc_rx_indicate_rsp(
717         conn_handle,
718         ble_gatts_notify_test_chr_1_def_handle + 1);
719 
720     /* Verify indication sent properly. */
721     ble_gatts_notify_test_misc_verify_tx_i(
722         conn_handle,
723         ble_gatts_notify_test_chr_2_def_handle + 1,
724         ble_gatts_notify_test_chr_2_val,
725         ble_gatts_notify_test_chr_2_len);
726 
727     /* Receive the confirmation for the second indication. */
728     ble_gatts_notify_test_misc_rx_indicate_rsp(
729         conn_handle,
730         ble_gatts_notify_test_chr_2_def_handle + 1);
731 
732     /* Verify no pending GATT jobs. */
733     TEST_ASSERT(!ble_gattc_any_jobs());
734 
735     /***
736      * Disconnect, modify characteristic values, and reconnect.  Ensure
737      * indications are not sent and are no longer enabled.
738      */
739 
740     ble_gatts_notify_test_disconnect(conn_handle,
741                                      BLE_GATTS_CLT_CFG_F_INDICATE, 0,
742                                      BLE_GATTS_CLT_CFG_F_INDICATE, 0);
743 
744     /* Update characteristic 1's value. */
745     ble_gatts_notify_test_chr_1_len = 1;
746     ble_gatts_notify_test_chr_1_val[0] = 0xdd;
747     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
748 
749     /* Update characteristic 2's value. */
750     ble_gatts_notify_test_chr_2_len = 16;
751     memcpy(ble_gatts_notify_test_chr_2_val,
752            ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
753     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
754 
755     ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
756                                  ble_gatts_notify_test_util_gap_event, NULL);
757 
758     /* Ensure no indications sent. */
759     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
760 
761     /* Ensure indications disabled. */
762     flags = ble_gatts_notify_test_misc_read_notify(
763         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
764     TEST_ASSERT(flags == 0);
765     flags = ble_gatts_notify_test_misc_read_notify(
766         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
767     TEST_ASSERT(flags == 0);
768 }
769 
TEST_CASE(ble_gatts_notify_test_bonded_n)770 TEST_CASE(ble_gatts_notify_test_bonded_n)
771 {
772     uint16_t conn_handle;
773     uint16_t flags;
774 
775     ble_gatts_notify_test_misc_init(&conn_handle, 1,
776                                     BLE_GATTS_CLT_CFG_F_NOTIFY,
777                                     BLE_GATTS_CLT_CFG_F_NOTIFY);
778 
779     /* Disconnect. */
780     ble_gatts_notify_test_disconnect(conn_handle,
781                                      BLE_GATTS_CLT_CFG_F_NOTIFY, 0,
782                                      BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
783 
784     /* Ensure both CCCDs still persisted. */
785     TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
786 
787     /* Update characteristic 1's value. */
788     ble_gatts_notify_test_chr_1_len = 1;
789     ble_gatts_notify_test_chr_1_val[0] = 0xdd;
790     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
791 
792     /* Update characteristic 2's value. */
793     ble_gatts_notify_test_chr_2_len = 16;
794     memcpy(ble_gatts_notify_test_chr_2_val,
795            ((uint8_t[]){1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}), 16);
796     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
797 
798     /* Reconnect; ensure notifications don't get sent while unbonded and that
799      * notifications appear disabled.
800      */
801 
802     ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
803                                  ble_gatts_notify_test_util_gap_event, NULL);
804 
805     ble_gatts_notify_test_num_events = 0;
806     /* Ensure no notifications sent. */
807     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
808 
809     /* Ensure notifications disabled. */
810     flags = ble_gatts_notify_test_misc_read_notify(
811         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
812     TEST_ASSERT(flags == 0);
813     flags = ble_gatts_notify_test_misc_read_notify(
814         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
815     TEST_ASSERT(flags == 0);
816 
817     /* Simulate a successful encryption procedure (bonding restoration). */
818     ble_gatts_notify_test_restore_bonding(conn_handle,
819                                           BLE_GATTS_CLT_CFG_F_NOTIFY, 1,
820                                           BLE_GATTS_CLT_CFG_F_NOTIFY, 1);
821 
822     /* Ensure notifications enabled. */
823     flags = ble_gatts_notify_test_misc_read_notify(
824         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
825     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
826     flags = ble_gatts_notify_test_misc_read_notify(
827         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
828     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_NOTIFY);
829 
830     /* Ensure both CCCDs still persisted. */
831     TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
832 }
833 
TEST_CASE(ble_gatts_notify_test_bonded_i)834 TEST_CASE(ble_gatts_notify_test_bonded_i)
835 {
836     uint16_t conn_handle;
837     uint16_t flags;
838 
839     ble_gatts_notify_test_misc_init(&conn_handle, 1,
840                                     BLE_GATTS_CLT_CFG_F_INDICATE,
841                                     BLE_GATTS_CLT_CFG_F_INDICATE);
842 
843     /* Disconnect. */
844     ble_gatts_notify_test_disconnect(conn_handle,
845                                      BLE_GATTS_CLT_CFG_F_INDICATE, 0,
846                                      BLE_GATTS_CLT_CFG_F_INDICATE, 0);
847 
848     /* Ensure both CCCDs still persisted. */
849     TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
850 
851     /* Update characteristic 1's value. */
852     ble_gatts_notify_test_chr_1_len = 1;
853     ble_gatts_notify_test_chr_1_val[0] = 0xab;
854     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
855 
856     /* Update characteristic 2's value. */
857     ble_gatts_notify_test_chr_2_len = 16;
858     memcpy(ble_gatts_notify_test_chr_2_val,
859            ((uint8_t[]){0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}), 16);
860     ble_gatts_chr_updated(ble_gatts_notify_test_chr_2_def_handle + 1);
861 
862     /* Reconnect; ensure notifications don't get sent while unbonded and that
863      * notifications appear disabled.
864      */
865 
866     ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
867                                  ble_gatts_notify_test_util_gap_event, NULL);
868 
869     /* Ensure no indications sent. */
870     TEST_ASSERT(ble_hs_test_util_prev_tx_dequeue() == NULL);
871 
872     /* Ensure notifications disabled. */
873     flags = ble_gatts_notify_test_misc_read_notify(
874         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
875     TEST_ASSERT(flags == 0);
876     flags = ble_gatts_notify_test_misc_read_notify(
877         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
878     TEST_ASSERT(flags == 0);
879 
880     /* Simulate a successful encryption procedure (bonding restoration). */
881     ble_gatts_notify_test_restore_bonding(conn_handle,
882                                           BLE_GATTS_CLT_CFG_F_INDICATE, 1,
883                                           BLE_GATTS_CLT_CFG_F_INDICATE, 0);
884 
885     /* Verify the second indication doesn't get sent until the first is
886      * confirmed.
887      */
888     TEST_ASSERT(ble_hs_test_util_prev_tx_queue_sz() == 0);
889 
890     /* Receive the confirmation for the first indication. */
891     ble_gatts_notify_test_misc_rx_indicate_rsp(
892         conn_handle,
893         ble_gatts_notify_test_chr_1_def_handle + 1);
894 
895     /* Verify indication sent properly. */
896     ble_gatts_notify_test_misc_verify_tx_i(
897         conn_handle,
898         ble_gatts_notify_test_chr_2_def_handle + 1,
899         ble_gatts_notify_test_chr_2_val,
900         ble_gatts_notify_test_chr_2_len);
901 
902     /* Receive the confirmation for the second indication. */
903     ble_gatts_notify_test_misc_rx_indicate_rsp(
904         conn_handle,
905         ble_gatts_notify_test_chr_2_def_handle + 1);
906 
907     /* Verify no pending GATT jobs. */
908     TEST_ASSERT(!ble_gattc_any_jobs());
909 
910     /* Ensure notifications enabled. */
911     flags = ble_gatts_notify_test_misc_read_notify(
912         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
913     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
914     flags = ble_gatts_notify_test_misc_read_notify(
915         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
916     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
917 
918     /* Ensure both CCCDs still persisted. */
919     TEST_ASSERT(ble_hs_test_util_num_cccds() == 2);
920 }
921 
TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)922 TEST_CASE(ble_gatts_notify_test_bonded_i_no_ack)
923 {
924     struct ble_store_value_cccd value_cccd;
925     struct ble_store_key_cccd key_cccd;
926     uint16_t conn_handle;
927     uint16_t flags;
928     int rc;
929 
930     ble_gatts_notify_test_misc_init(&conn_handle, 1,
931                                     BLE_GATTS_CLT_CFG_F_INDICATE, 0);
932 
933     /* Update characteristic 1's value. */
934     ble_gatts_notify_test_chr_1_len = 1;
935     ble_gatts_notify_test_chr_1_val[0] = 0xab;
936     ble_gatts_chr_updated(ble_gatts_notify_test_chr_1_def_handle + 1);
937 
938     /* Verify indication sent properly. */
939     ble_gatts_notify_test_misc_verify_tx_i(
940         conn_handle,
941         ble_gatts_notify_test_chr_1_def_handle + 1,
942         ble_gatts_notify_test_chr_1_val,
943         ble_gatts_notify_test_chr_1_len);
944 
945     /* Verify 'updated' state is still persisted. */
946     key_cccd.peer_addr = *BLE_ADDR_ANY;
947     key_cccd.chr_val_handle = ble_gatts_notify_test_chr_1_def_handle + 1;
948     key_cccd.idx = 0;
949 
950     rc = ble_store_read_cccd(&key_cccd, &value_cccd);
951     TEST_ASSERT_FATAL(rc == 0);
952     TEST_ASSERT(value_cccd.value_changed);
953 
954     /* Disconnect. */
955     ble_gatts_notify_test_disconnect(conn_handle,
956                                      BLE_GATTS_CLT_CFG_F_INDICATE, 1, 0, 0);
957 
958     /* Ensure CCCD still persisted. */
959     TEST_ASSERT(ble_hs_test_util_num_cccds() == 1);
960 
961     /* Reconnect. */
962     ble_hs_test_util_create_conn(conn_handle, ((uint8_t[]){2,3,4,5,6,7,8,9}),
963                                  ble_gatts_notify_test_util_gap_event, NULL);
964 
965     /* Simulate a successful encryption procedure (bonding restoration). */
966     ble_gatts_notify_test_restore_bonding(conn_handle,
967                                           BLE_GATTS_CLT_CFG_F_INDICATE, 1,
968                                           0, 0);
969 
970     /* Receive the confirmation for the indication. */
971     ble_gatts_notify_test_misc_rx_indicate_rsp(
972         conn_handle,
973         ble_gatts_notify_test_chr_1_def_handle + 1);
974 
975     /* Verify no pending GATT jobs. */
976     TEST_ASSERT(!ble_gattc_any_jobs());
977 
978     /* Ensure indication enabled. */
979     flags = ble_gatts_notify_test_misc_read_notify(
980         conn_handle, ble_gatts_notify_test_chr_1_def_handle);
981     TEST_ASSERT(flags == BLE_GATTS_CLT_CFG_F_INDICATE);
982     flags = ble_gatts_notify_test_misc_read_notify(
983         conn_handle, ble_gatts_notify_test_chr_2_def_handle);
984     TEST_ASSERT(flags == 0);
985 
986     /* Ensure CCCD still persisted. */
987     TEST_ASSERT(ble_hs_test_util_num_cccds() == 1);
988 
989     /* Verify 'updated' state is no longer persisted. */
990     rc = ble_store_read_cccd(&key_cccd, &value_cccd);
991     TEST_ASSERT_FATAL(rc == 0);
992     TEST_ASSERT(!value_cccd.value_changed);
993 }
994 
TEST_CASE(ble_gatts_notify_test_disallowed)995 TEST_CASE(ble_gatts_notify_test_disallowed)
996 {
997     uint16_t chr1_val_handle;
998     uint16_t chr2_val_handle;
999     uint16_t chr3_val_handle;
1000 
1001     const struct ble_gatt_svc_def svcs[] = { {
1002         .type = BLE_GATT_SVC_TYPE_PRIMARY,
1003         .uuid = BLE_UUID16_DECLARE(0x1234),
1004         .characteristics = (struct ble_gatt_chr_def[]) { {
1005             .uuid = BLE_UUID16_DECLARE(1),
1006             .access_cb = ble_gatts_notify_test_misc_access,
1007             .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
1008             .val_handle = &chr1_val_handle,
1009         }, {
1010             .uuid = BLE_UUID16_DECLARE(2),
1011             .access_cb = ble_gatts_notify_test_misc_access,
1012             .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_INDICATE,
1013             .val_handle = &chr2_val_handle,
1014         }, {
1015             .uuid = BLE_UUID16_DECLARE(3),
1016             .access_cb = ble_gatts_notify_test_misc_access,
1017             .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY |
1018                      BLE_GATT_CHR_F_INDICATE,
1019             .val_handle = &chr3_val_handle,
1020         }, {
1021             0
1022         } },
1023     }, {
1024         0
1025     } };
1026 
1027     ble_hs_test_util_init();
1028 
1029     ble_hs_test_util_reg_svcs(svcs, NULL, NULL);
1030     TEST_ASSERT_FATAL(chr1_val_handle != 0);
1031     TEST_ASSERT_FATAL(chr2_val_handle != 0);
1032     TEST_ASSERT_FATAL(chr3_val_handle != 0);
1033 
1034     ble_hs_test_util_create_conn(2, ble_gatts_notify_test_peer_addr,
1035                                  ble_gatts_notify_test_util_gap_event, NULL);
1036 
1037     /* Attempt to enable notifications on chr1 should succeed. */
1038     ble_gatts_notify_test_misc_try_enable_notify(
1039         2, chr1_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
1040 
1041     /* Attempt to enable indications on chr1 should fail. */
1042     ble_gatts_notify_test_misc_try_enable_notify(
1043         2, chr1_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 1);
1044 
1045     /* Attempt to enable notifications on chr2 should fail. */
1046     ble_gatts_notify_test_misc_try_enable_notify(
1047         2, chr2_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 1);
1048 
1049     /* Attempt to enable indications on chr2 should succeed. */
1050     ble_gatts_notify_test_misc_try_enable_notify(
1051         2, chr2_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 0);
1052 
1053     /* Attempt to enable notifications on chr3 should succeed. */
1054     ble_gatts_notify_test_misc_try_enable_notify(
1055         2, chr3_val_handle - 1, BLE_GATTS_CLT_CFG_F_NOTIFY, 0);
1056 
1057     /* Attempt to enable indications on chr3 should succeed. */
1058     ble_gatts_notify_test_misc_try_enable_notify(
1059         2, chr3_val_handle - 1, BLE_GATTS_CLT_CFG_F_INDICATE, 0);
1060 }
1061 
TEST_SUITE(ble_gatts_notify_suite)1062 TEST_SUITE(ble_gatts_notify_suite)
1063 {
1064     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
1065 
1066     ble_gatts_notify_test_n();
1067     ble_gatts_notify_test_i();
1068 
1069     ble_gatts_notify_test_bonded_n();
1070     ble_gatts_notify_test_bonded_i();
1071 
1072     ble_gatts_notify_test_bonded_i_no_ack();
1073 
1074     ble_gatts_notify_test_disallowed();
1075 
1076     /* XXX: Test corner cases:
1077      *     o Bonding after CCCD configuration.
1078      *     o Disconnect prior to rx of indicate ack.
1079      */
1080 }
1081 
1082 int
ble_gatts_notify_test_all(void)1083 ble_gatts_notify_test_all(void)
1084 {
1085     ble_gatts_notify_suite();
1086 
1087     return tu_any_failed;
1088 }
1089