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