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