xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_gatts_read_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 "host/ble_uuid.h"
24 #include "host/ble_hs_test.h"
25 #include "ble_hs_test_util.h"
26 
27 #define BLE_GATTS_READ_TEST_CHR_1_UUID    0x1111
28 #define BLE_GATTS_READ_TEST_CHR_2_UUID    0x2222
29 
30 static uint8_t ble_gatts_read_test_peer_addr[6] = {2,3,4,5,6,7};
31 
32 static int
33 ble_gatts_read_test_util_access_1(uint16_t conn_handle,
34                                   uint16_t attr_handle,
35                                   struct ble_gatt_access_ctxt *ctxt,
36                                   void *arg);
37 
38 static int
39 ble_gatts_read_test_util_access_2(uint16_t conn_handle,
40                                   uint16_t attr_handle,
41                                   struct ble_gatt_access_ctxt *ctxt,
42                                   void *arg);
43 static void
44 ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
45                                 void *arg);
46 
47 static const struct ble_gatt_svc_def ble_gatts_read_test_svcs[] = { {
48     .type = BLE_GATT_SVC_TYPE_PRIMARY,
49     .uuid = BLE_UUID16_DECLARE(0x1234),
50     .characteristics = (struct ble_gatt_chr_def[]) { {
51         .uuid = BLE_UUID16_DECLARE(BLE_GATTS_READ_TEST_CHR_1_UUID),
52         .access_cb = ble_gatts_read_test_util_access_1,
53         .flags = BLE_GATT_CHR_F_READ
54     }, {
55         .uuid = BLE_UUID16_DECLARE(BLE_GATTS_READ_TEST_CHR_2_UUID),
56         .access_cb = ble_gatts_read_test_util_access_2,
57         .flags = BLE_GATT_CHR_F_READ
58     }, {
59         0
60     } },
61 }, {
62     0
63 } };
64 
65 static uint16_t ble_gatts_read_test_chr_1_def_handle;
66 static uint16_t ble_gatts_read_test_chr_1_val_handle;
67 static uint8_t ble_gatts_read_test_chr_1_val[1024];
68 static int ble_gatts_read_test_chr_1_len;
69 static uint16_t ble_gatts_read_test_chr_2_def_handle;
70 static uint16_t ble_gatts_read_test_chr_2_val_handle;
71 
72 static void
ble_gatts_read_test_misc_init(uint16_t * out_conn_handle)73 ble_gatts_read_test_misc_init(uint16_t *out_conn_handle)
74 {
75     ble_hs_test_util_init();
76 
77     ble_hs_test_util_reg_svcs(ble_gatts_read_test_svcs,
78                               ble_gatts_read_test_misc_reg_cb,
79                               NULL);
80     TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_def_handle != 0);
81     TEST_ASSERT_FATAL(ble_gatts_read_test_chr_1_val_handle ==
82                       ble_gatts_read_test_chr_1_def_handle + 1);
83     TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_def_handle != 0);
84     TEST_ASSERT_FATAL(ble_gatts_read_test_chr_2_val_handle ==
85                       ble_gatts_read_test_chr_2_def_handle + 1);
86 
87     ble_hs_test_util_create_conn(2, ble_gatts_read_test_peer_addr, NULL, NULL);
88 
89     if (out_conn_handle != NULL) {
90         *out_conn_handle = 2;
91     }
92 }
93 
94 static void
ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt * ctxt,void * arg)95 ble_gatts_read_test_misc_reg_cb(struct ble_gatt_register_ctxt *ctxt,
96                                 void *arg)
97 {
98     uint16_t uuid16;
99 
100     if (ctxt->op == BLE_GATT_REGISTER_OP_CHR) {
101         uuid16 = ble_uuid_u16(ctxt->chr.chr_def->uuid);
102         switch (uuid16) {
103         case BLE_GATTS_READ_TEST_CHR_1_UUID:
104             ble_gatts_read_test_chr_1_def_handle = ctxt->chr.def_handle;
105             ble_gatts_read_test_chr_1_val_handle = ctxt->chr.val_handle;
106             break;
107 
108         case BLE_GATTS_READ_TEST_CHR_2_UUID:
109             ble_gatts_read_test_chr_2_def_handle = ctxt->chr.def_handle;
110             ble_gatts_read_test_chr_2_val_handle = ctxt->chr.val_handle;
111             break;
112 
113         default:
114             TEST_ASSERT_FATAL(0);
115             break;
116         }
117     }
118 }
119 
120 static int
ble_gatts_read_test_util_access_1(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)121 ble_gatts_read_test_util_access_1(uint16_t conn_handle,
122                                   uint16_t attr_handle,
123                                   struct ble_gatt_access_ctxt *ctxt,
124                                   void *arg)
125 {
126     int rc;
127 
128     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
129     TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_1_val_handle);
130 
131     TEST_ASSERT(ctxt->chr ==
132                 &ble_gatts_read_test_svcs[0].characteristics[0]);
133 
134     rc = os_mbuf_append(ctxt->om, ble_gatts_read_test_chr_1_val,
135                         ble_gatts_read_test_chr_1_len);
136     TEST_ASSERT(rc == 0);
137 
138     return 0;
139 }
140 
141 static int
ble_gatts_read_test_util_access_2(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)142 ble_gatts_read_test_util_access_2(uint16_t conn_handle,
143                                   uint16_t attr_handle,
144                                   struct ble_gatt_access_ctxt *ctxt,
145                                   void *arg)
146 {
147     uint8_t *buf;
148 
149     TEST_ASSERT_FATAL(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
150     TEST_ASSERT_FATAL(attr_handle == ble_gatts_read_test_chr_2_def_handle + 1);
151 
152     TEST_ASSERT(ctxt->chr ==
153                 &ble_gatts_read_test_svcs[0].characteristics[1]);
154 
155     buf = os_mbuf_extend(ctxt->om, 6);
156     TEST_ASSERT_FATAL(buf != NULL);
157 
158     buf[0] = 0;
159     buf[1] = 10;
160     buf[2] = 20;
161     buf[3] = 30;
162     buf[4] = 40;
163     buf[5] = 50;
164 
165     return 0;
166 }
167 
168 static void
ble_gatts_read_test_once(uint16_t conn_handle,uint16_t attr_id,void * expected_value,uint16_t expected_len)169 ble_gatts_read_test_once(uint16_t conn_handle, uint16_t attr_id,
170                          void *expected_value, uint16_t expected_len)
171 {
172     struct ble_att_read_req read_req;
173     uint8_t buf[BLE_ATT_READ_REQ_SZ];
174     int rc;
175 
176     read_req.barq_handle = attr_id;
177     ble_att_read_req_write(buf, sizeof buf, &read_req);
178 
179     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
180                                                 buf, sizeof buf);
181     TEST_ASSERT(rc == 0);
182 
183     ble_hs_test_util_verify_tx_read_rsp(expected_value, expected_len);
184 }
185 
TEST_CASE(ble_gatts_read_test_case_basic)186 TEST_CASE(ble_gatts_read_test_case_basic)
187 {
188     uint16_t conn_handle;
189 
190     ble_gatts_read_test_misc_init(&conn_handle);
191 
192     /*** Application points attribute at static data. */
193     ble_gatts_read_test_chr_1_val[0] = 1;
194     ble_gatts_read_test_chr_1_val[1] = 2;
195     ble_gatts_read_test_chr_1_val[2] = 3;
196     ble_gatts_read_test_chr_1_len = 3;
197     ble_gatts_read_test_once(conn_handle,
198                              ble_gatts_read_test_chr_1_val_handle,
199                              ble_gatts_read_test_chr_1_val,
200                              ble_gatts_read_test_chr_1_len);
201 
202     /*** Application uses stack-provided buffer for dynamic attribute. */
203     ble_gatts_read_test_once(conn_handle,
204                              ble_gatts_read_test_chr_2_def_handle + 1,
205                              ((uint8_t[6]){0,10,20,30,40,50}), 6);
206 
207 }
208 
TEST_CASE(ble_gatts_read_test_case_long)209 TEST_CASE(ble_gatts_read_test_case_long)
210 {
211     struct ble_att_read_blob_req read_blob_req;
212     struct ble_att_read_req read_req;
213     uint8_t buf[max(BLE_ATT_READ_REQ_SZ, BLE_ATT_READ_BLOB_REQ_SZ)];
214     uint16_t conn_handle;
215     int rc;
216     int i;
217 
218     ble_gatts_read_test_misc_init(&conn_handle);
219 
220     /*** Prepare characteristic value. */
221     ble_gatts_read_test_chr_1_len = 40;
222     for (i = 0; i < ble_gatts_read_test_chr_1_len; i++) {
223         ble_gatts_read_test_chr_1_val[i] = i;
224     }
225 
226     /* Receive first read request. */
227     read_req.barq_handle = ble_gatts_read_test_chr_1_val_handle;
228     ble_att_read_req_write(buf, sizeof buf, &read_req);
229 
230     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
231                                                 buf, sizeof buf);
232     TEST_ASSERT(rc == 0);
233 
234     ble_hs_test_util_verify_tx_read_rsp(ble_gatts_read_test_chr_1_val, 22);
235 
236     /* Receive follow-up read blob request. */
237     read_blob_req.babq_handle = ble_gatts_read_test_chr_1_val_handle;
238     read_blob_req.babq_offset = 22;
239     ble_att_read_blob_req_write(buf, sizeof buf, &read_blob_req);
240 
241     rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
242                                                 buf, sizeof buf);
243     TEST_ASSERT(rc == 0);
244 
245     /* Ensure response starts at appropriate offset (22). */
246     ble_hs_test_util_verify_tx_read_blob_rsp(
247         ble_gatts_read_test_chr_1_val + 22, 18);
248 }
249 
TEST_SUITE(ble_gatts_read_test_suite)250 TEST_SUITE(ble_gatts_read_test_suite)
251 {
252     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
253 
254     ble_gatts_read_test_case_basic();
255     ble_gatts_read_test_case_long();
256 }
257