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 <assert.h>
21 #include <string.h>
22 #include "host/ble_hs.h"
23 #include "host/ble_uuid.h"
24 #include "host/ble_gatt.h"
25 #include "btshell.h"
26
27 #include "nimble/npl_shell.h"
28
29 /* 0000xxxx-8c26-476f-89a7-a108033a69c7 */
30 #define PTS_UUID_DECLARE(uuid16) \
31 ((const ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT( \
32 0xc7, 0x69, 0x3a, 0x03, 0x08, 0xa1, 0xa7, 0x89, \
33 0x6f, 0x47, 0x26, 0x8c, uuid16, uuid16 >> 8, 0x00, 0x00 \
34 )))
35
36 #define PTS_SVC 0x0001
37 #define PTS_CHR_READ 0x0002
38 #define PTS_CHR_WRITE 0x0003
39 #define PTS_CHR_RELIABLE_WRITE 0x0004
40 #define PTS_CHR_WRITE_NO_RSP 0x0005
41 #define PTS_CHR_READ_WRITE 0x0006
42 #define PTS_CHR_READ_WRITE_ENC 0x0007
43 #define PTS_CHR_READ_WRITE_AUTHEN 0x0008
44 #define PTS_DSC_READ 0x0009
45 #define PTS_DSC_WRITE 0x000a
46 #define PTS_DSC_READ_WRITE 0x000b
47 #define PTS_DSC_READ_WRITE_ENC 0x000c
48 #define PTS_DSC_READ_WRITE_AUTHEN 0x000d
49
50 #define PTS_LONG_SVC 0x0011
51 #define PTS_LONG_CHR_READ 0x0012
52 #define PTS_LONG_CHR_WRITE 0x0013
53 #define PTS_LONG_CHR_RELIABLE_WRITE 0x0014
54 #define PTS_LONG_CHR_READ_WRITE 0x0015
55 #define PTS_LONG_CHR_READ_WRITE_ALT 0x0016
56 #define PTS_LONG_CHR_READ_WRITE_ENC 0x0017
57 #define PTS_LONG_CHR_READ_WRITE_AUTHEN 0x0018
58 #define PTS_LONG_DSC_READ 0x0019
59 #define PTS_LONG_DSC_WRITE 0x001a
60 #define PTS_LONG_DSC_READ_WRITE 0x001b
61 #define PTS_LONG_DSC_READ_WRITE_ENC 0x001c
62 #define PTS_LONG_DSC_READ_WRITE_AUTHEN 0x001d
63
64 /**
65 * The vendor specific security test service consists of two characteristics:
66 * o random-number-generator: generates a random 32-bit number each time
67 * it is read. This characteristic can only be read over an encrypted
68 * connection.
69 * o static-value: a single-byte characteristic that can always be read,
70 * but can only be written over an encrypted connection.
71 */
72
73 /* 59462f12-9543-9999-12c8-58b459a2712d */
74 static const ble_uuid128_t gatt_svr_svc_sec_test_uuid =
75 BLE_UUID128_INIT(0x2d, 0x71, 0xa2, 0x59, 0xb4, 0x58, 0xc8, 0x12,
76 0x99, 0x99, 0x43, 0x95, 0x12, 0x2f, 0x46, 0x59);
77
78 /* 5c3a659e-897e-45e1-b016-007107c96df6 */
79 static const ble_uuid128_t gatt_svr_chr_sec_test_rand_uuid =
80 BLE_UUID128_INIT(0xf6, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0,
81 0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c);
82
83 /* 5c3a659e-897e-45e1-b016-007107c96df7 */
84 static const ble_uuid128_t gatt_svr_chr_sec_test_static_uuid =
85 BLE_UUID128_INIT(0xf7, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0,
86 0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c);
87
88 /* 5c3a659e-897e-45e1-b016-007107c96df8 */
89 static const ble_uuid128_t gatt_svr_chr_sec_test_static_auth_uuid =
90 BLE_UUID128_INIT(0xf8, 0x6d, 0xc9, 0x07, 0x71, 0x00, 0x16, 0xb0,
91 0xe1, 0x45, 0x7e, 0x89, 0x9e, 0x65, 0x3a, 0x5c);
92
93 static uint8_t gatt_svr_sec_test_static_val;
94
95 static uint8_t gatt_svr_pts_static_val;
96 static uint8_t gatt_svr_pts_static_long_val[30];
97 static uint8_t gatt_svr_pts_static_long_val_alt[30];
98
99 static int
100 gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
101 struct ble_gatt_access_ctxt *ctxt,
102 void *arg);
103
104 static int
105 gatt_svr_access_test(uint16_t conn_handle, uint16_t attr_handle,
106 struct ble_gatt_access_ctxt *ctxt,
107 void *arg);
108
109 static int
110 gatt_svr_long_access_test(uint16_t conn_handle, uint16_t attr_handle,
111 struct ble_gatt_access_ctxt *ctxt,
112 void *arg);
113
114 static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
115 {
116 /*** Service: PTS test. */
117 .type = BLE_GATT_SVC_TYPE_PRIMARY,
118 .uuid = PTS_UUID_DECLARE(PTS_SVC),
119 .characteristics = (struct ble_gatt_chr_def[]) { {
120 .uuid = PTS_UUID_DECLARE(PTS_CHR_READ),
121 .access_cb = gatt_svr_access_test,
122 .flags = BLE_GATT_CHR_F_READ,
123 }, {
124 .uuid = PTS_UUID_DECLARE(PTS_CHR_WRITE),
125 .access_cb = gatt_svr_access_test,
126 .flags = BLE_GATT_CHR_F_WRITE,
127 }, {
128 .uuid = PTS_UUID_DECLARE(PTS_CHR_RELIABLE_WRITE),
129 .access_cb = gatt_svr_access_test,
130 .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_RELIABLE_WRITE,
131 }, {
132 .uuid = PTS_UUID_DECLARE(PTS_CHR_WRITE_NO_RSP),
133 .access_cb = gatt_svr_access_test,
134 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE_NO_RSP,
135 }, {
136 .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE),
137 .access_cb = gatt_svr_access_test,
138 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
139 }, {
140 .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_ENC),
141 .access_cb = gatt_svr_access_test,
142 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC |
143 BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
144 .min_key_size = 16,
145 }, {
146 .uuid = PTS_UUID_DECLARE(PTS_CHR_READ_WRITE_AUTHEN),
147 .access_cb = gatt_svr_access_test,
148 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN |
149 BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
150
151 .descriptors = (struct ble_gatt_dsc_def[]){ {
152 .uuid = PTS_UUID_DECLARE(PTS_DSC_READ),
153 .access_cb = gatt_svr_access_test,
154 .att_flags = BLE_ATT_F_READ,
155 }, {
156 .uuid = PTS_UUID_DECLARE(PTS_DSC_WRITE),
157 .access_cb = gatt_svr_access_test,
158 .att_flags = BLE_ATT_F_WRITE,
159 }, {
160 .uuid = PTS_UUID_DECLARE(PTS_DSC_READ_WRITE),
161 .access_cb = gatt_svr_access_test,
162 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE,
163 }, {
164 .uuid = PTS_UUID_DECLARE(PTS_DSC_READ_WRITE_ENC),
165 .access_cb = gatt_svr_access_test,
166 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_READ_ENC |
167 BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_ENC,
168 .min_key_size = 16,
169 }, {
170 .uuid = PTS_UUID_DECLARE(PTS_DSC_READ_WRITE_AUTHEN),
171 .access_cb = gatt_svr_access_test,
172 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_READ_AUTHEN |
173 BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_AUTHEN,
174 }, {
175 0, /* No more descriptors in this characteristic. */
176 } }
177 }, {
178 0, /* No more characteristics in this service. */
179 } },
180 },
181
182 {
183 /*** Service: PTS long test. */
184 .type = BLE_GATT_SVC_TYPE_PRIMARY,
185 .uuid = PTS_UUID_DECLARE(PTS_LONG_SVC),
186 .characteristics = (struct ble_gatt_chr_def[]) { {
187 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ),
188 .access_cb = gatt_svr_long_access_test,
189 .flags = BLE_GATT_CHR_F_READ,
190 }, {
191 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_WRITE),
192 .access_cb = gatt_svr_long_access_test,
193 .flags = BLE_GATT_CHR_F_WRITE,
194 }, {
195 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_RELIABLE_WRITE),
196 .access_cb = gatt_svr_long_access_test,
197 .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_RELIABLE_WRITE,
198 }, {
199 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE),
200 .access_cb = gatt_svr_long_access_test,
201 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
202 }, {
203 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE_ALT),
204 .access_cb = gatt_svr_long_access_test,
205 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE,
206 }, {
207 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE_ENC),
208 .access_cb = gatt_svr_long_access_test,
209 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC |
210 BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
211 .min_key_size = 16,
212 }, {
213 .uuid = PTS_UUID_DECLARE(PTS_LONG_CHR_READ_WRITE_AUTHEN),
214 .access_cb = gatt_svr_long_access_test,
215 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN |
216 BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_AUTHEN,
217
218 .descriptors = (struct ble_gatt_dsc_def[]){ {
219 .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_READ),
220 .access_cb = gatt_svr_long_access_test,
221 .att_flags = BLE_ATT_F_READ,
222 }, {
223 .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_WRITE),
224 .access_cb = gatt_svr_long_access_test,
225 .att_flags = BLE_ATT_F_WRITE,
226 }, {
227 .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_READ_WRITE),
228 .access_cb = gatt_svr_long_access_test,
229 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE,
230 }, {
231 .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_READ_WRITE_ENC),
232 .access_cb = gatt_svr_long_access_test,
233 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_READ_ENC |
234 BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_ENC,
235 .min_key_size = 16,
236 }, {
237 .uuid = PTS_UUID_DECLARE(PTS_LONG_DSC_READ_WRITE_AUTHEN),
238 .access_cb = gatt_svr_long_access_test,
239 .att_flags = BLE_ATT_F_READ | BLE_ATT_F_READ_AUTHEN |
240 BLE_ATT_F_WRITE | BLE_ATT_F_WRITE_AUTHEN,
241 }, {
242 0, /* No more descriptors in this characteristic. */
243 } }
244 }, {
245 0, /* No more characteristics in this service. */
246 } },
247 },
248
249 {
250 /*** Service: Security test. */
251 .type = BLE_GATT_SVC_TYPE_PRIMARY,
252 .uuid = &gatt_svr_svc_sec_test_uuid.u,
253 .characteristics = (struct ble_gatt_chr_def[]) { {
254 /*** Characteristic: Random number generator. */
255 .uuid = &gatt_svr_chr_sec_test_rand_uuid.u,
256 .access_cb = gatt_svr_chr_access_sec_test,
257 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC,
258 }, {
259 /*** Characteristic: Static value. */
260 .uuid = &gatt_svr_chr_sec_test_static_uuid.u,
261 .access_cb = gatt_svr_chr_access_sec_test,
262 .flags = BLE_GATT_CHR_F_READ |
263 BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_ENC,
264 }, {
265 /*** Characteristic: Static value. */
266 .uuid = &gatt_svr_chr_sec_test_static_auth_uuid.u,
267 .access_cb = gatt_svr_chr_access_sec_test,
268 .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_AUTHEN,
269 }, {
270 0, /* No more characteristics in this service. */
271 } },
272 },
273
274 {
275 0, /* No more services. */
276 },
277 };
278
279 static int
gatt_svr_chr_write(struct os_mbuf * om,uint16_t min_len,uint16_t max_len,void * dst,uint16_t * len)280 gatt_svr_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len,
281 void *dst, uint16_t *len)
282 {
283 uint16_t om_len;
284 int rc;
285
286 om_len = OS_MBUF_PKTLEN(om);
287 if (om_len < min_len || om_len > max_len) {
288 return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN;
289 }
290
291 rc = ble_hs_mbuf_to_flat(om, dst, max_len, len);
292 if (rc != 0) {
293 return BLE_ATT_ERR_UNLIKELY;
294 }
295
296 return 0;
297 }
298
299 static int
gatt_svr_chr_access_sec_test(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)300 gatt_svr_chr_access_sec_test(uint16_t conn_handle, uint16_t attr_handle,
301 struct ble_gatt_access_ctxt *ctxt,
302 void *arg)
303 {
304 const ble_uuid_t *uuid;
305 int rand_num;
306 int rc;
307
308 uuid = ctxt->chr->uuid;
309
310 /* Determine which characteristic is being accessed by examining its
311 * 128-bit UUID.
312 */
313
314 if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_rand_uuid.u) == 0) {
315 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
316
317 /* Respond with a 32-bit random number. */
318 rand_num = rand();
319 rc = os_mbuf_append(ctxt->om, &rand_num, sizeof rand_num);
320 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
321 }
322
323 if (ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_static_uuid.u) == 0 ||
324 ble_uuid_cmp(uuid, &gatt_svr_chr_sec_test_static_auth_uuid.u) == 0) {
325 switch (ctxt->op) {
326 case BLE_GATT_ACCESS_OP_READ_CHR:
327 rc = os_mbuf_append(ctxt->om, &gatt_svr_sec_test_static_val,
328 sizeof gatt_svr_sec_test_static_val);
329 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
330
331 case BLE_GATT_ACCESS_OP_WRITE_CHR:
332 rc = gatt_svr_chr_write(ctxt->om,
333 sizeof gatt_svr_sec_test_static_val,
334 sizeof gatt_svr_sec_test_static_val,
335 &gatt_svr_sec_test_static_val, NULL);
336 return rc;
337
338 default:
339 assert(0);
340 return BLE_ATT_ERR_UNLIKELY;
341 }
342 }
343
344 /* Unknown characteristic; the nimble stack should not have called this
345 * function.
346 */
347 assert(0);
348 return BLE_ATT_ERR_UNLIKELY;
349 }
350
351 /* This method is used for PTS testing only, to extract 16 bit value
352 * from 128 bit vendor specific UUID.
353 */
354 static uint16_t
extract_uuid16_from_pts_uuid128(const ble_uuid_t * uuid)355 extract_uuid16_from_pts_uuid128(const ble_uuid_t *uuid)
356 {
357 const uint8_t *u8ptr;
358 uint16_t uuid16;
359
360 u8ptr = BLE_UUID128(uuid)->value;
361 uuid16 = u8ptr[12];
362 uuid16 |= (uint16_t)u8ptr[13] << 8;
363 return uuid16;
364 }
365
366 static int
gatt_svr_access_test(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)367 gatt_svr_access_test(uint16_t conn_handle, uint16_t attr_handle,
368 struct ble_gatt_access_ctxt *ctxt,
369 void *arg)
370 {
371 uint16_t uuid16;
372 int rc;
373
374 uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
375 assert(uuid16 != 0);
376
377 switch (uuid16) {
378 case PTS_CHR_READ:
379 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
380 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
381 sizeof gatt_svr_pts_static_val);
382 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
383
384 case PTS_CHR_WRITE:
385 case PTS_CHR_RELIABLE_WRITE:
386 case PTS_CHR_WRITE_NO_RSP:
387 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
388 rc = gatt_svr_chr_write(ctxt->om,0,
389 sizeof gatt_svr_pts_static_val,
390 &gatt_svr_pts_static_val, NULL);
391 return rc;
392 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
393 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
394 sizeof gatt_svr_pts_static_val);
395 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
396 }
397
398 case PTS_CHR_READ_WRITE:
399 case PTS_CHR_READ_WRITE_ENC:
400 case PTS_CHR_READ_WRITE_AUTHEN:
401 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
402 rc = gatt_svr_chr_write(ctxt->om,0,
403 sizeof gatt_svr_pts_static_val,
404 &gatt_svr_pts_static_val, NULL);
405 return rc;
406 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
407 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
408 sizeof gatt_svr_pts_static_val);
409 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
410 }
411
412 case PTS_DSC_READ:
413 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC);
414 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
415 sizeof gatt_svr_pts_static_val);
416 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
417
418 case PTS_DSC_WRITE:
419 assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC);
420 rc = gatt_svr_chr_write(ctxt->om,0,
421 sizeof gatt_svr_pts_static_val,
422 &gatt_svr_pts_static_val, NULL);
423 return rc;
424
425 case PTS_DSC_READ_WRITE:
426 case PTS_DSC_READ_WRITE_ENC:
427 case PTS_DSC_READ_WRITE_AUTHEN:
428 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) {
429 rc = gatt_svr_chr_write(ctxt->om,0,
430 sizeof gatt_svr_pts_static_val,
431 &gatt_svr_pts_static_val, NULL);
432 return rc;
433 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
434 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_val,
435 sizeof gatt_svr_pts_static_val);
436 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
437 }
438
439 default:
440 assert(0);
441 return BLE_ATT_ERR_UNLIKELY;
442 }
443 }
444
445 static int
gatt_svr_long_access_test(uint16_t conn_handle,uint16_t attr_handle,struct ble_gatt_access_ctxt * ctxt,void * arg)446 gatt_svr_long_access_test(uint16_t conn_handle, uint16_t attr_handle,
447 struct ble_gatt_access_ctxt *ctxt,
448 void *arg)
449 {
450 uint16_t uuid16;
451 int rc;
452
453 uuid16 = extract_uuid16_from_pts_uuid128(ctxt->chr->uuid);
454 assert(uuid16 != 0);
455
456 switch (uuid16) {
457 case PTS_LONG_CHR_READ:
458 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR);
459 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
460 sizeof gatt_svr_pts_static_long_val);
461 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
462
463 case PTS_LONG_CHR_WRITE:
464 case PTS_LONG_CHR_RELIABLE_WRITE:
465 assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR);
466 rc = gatt_svr_chr_write(ctxt->om,0,
467 sizeof gatt_svr_pts_static_long_val,
468 &gatt_svr_pts_static_long_val, NULL);
469 return rc;
470
471 case PTS_LONG_CHR_READ_WRITE:
472 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
473 rc = gatt_svr_chr_write(ctxt->om,0,
474 sizeof gatt_svr_pts_static_long_val,
475 &gatt_svr_pts_static_long_val, NULL);
476 return rc;
477 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
478 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
479 sizeof gatt_svr_pts_static_long_val);
480 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
481 }
482
483 case PTS_LONG_CHR_READ_WRITE_ALT:
484 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
485 rc = gatt_svr_chr_write(ctxt->om,0,
486 sizeof gatt_svr_pts_static_long_val_alt,
487 &gatt_svr_pts_static_long_val_alt, NULL);
488 return rc;
489 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
490 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val_alt,
491 sizeof gatt_svr_pts_static_long_val_alt);
492 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
493 }
494
495 case PTS_LONG_CHR_READ_WRITE_ENC:
496 case PTS_LONG_CHR_READ_WRITE_AUTHEN:
497 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
498 rc = gatt_svr_chr_write(ctxt->om,0,
499 sizeof gatt_svr_pts_static_long_val,
500 &gatt_svr_pts_static_long_val, NULL);
501 return rc;
502 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
503 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
504 sizeof gatt_svr_pts_static_long_val);
505 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
506 }
507
508 case PTS_LONG_DSC_READ:
509 assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC);
510 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
511 sizeof gatt_svr_pts_static_long_val);
512 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
513
514 case PTS_LONG_DSC_WRITE:
515 assert(ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC);
516 rc = gatt_svr_chr_write(ctxt->om,0,
517 sizeof gatt_svr_pts_static_long_val,
518 &gatt_svr_pts_static_long_val, NULL);
519 return rc;
520
521 case PTS_LONG_DSC_READ_WRITE:
522 case PTS_LONG_DSC_READ_WRITE_ENC:
523 case PTS_LONG_DSC_READ_WRITE_AUTHEN:
524 if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_DSC) {
525 rc = gatt_svr_chr_write(ctxt->om,0,
526 sizeof gatt_svr_pts_static_long_val,
527 &gatt_svr_pts_static_long_val, NULL);
528 return rc;
529 } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_DSC) {
530 rc = os_mbuf_append(ctxt->om, &gatt_svr_pts_static_long_val,
531 sizeof gatt_svr_pts_static_long_val);
532 return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
533 }
534
535 default:
536 assert(0);
537 return BLE_ATT_ERR_UNLIKELY;
538 }
539 }
540
541 void
gatt_svr_register_cb(struct ble_gatt_register_ctxt * ctxt,void * arg)542 gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg)
543 {
544 char buf[BLE_UUID_STR_LEN];
545
546 switch (ctxt->op) {
547 case BLE_GATT_REGISTER_OP_SVC:
548 MODLOG_DFLT(DEBUG, "registered service %s with handle=%d\n",
549 ble_uuid_to_str(ctxt->svc.svc_def->uuid, buf),
550 ctxt->svc.handle);
551 break;
552
553 case BLE_GATT_REGISTER_OP_CHR:
554 MODLOG_DFLT(DEBUG, "registering characteristic %s with "
555 "def_handle=%d val_handle=%d\n",
556 ble_uuid_to_str(ctxt->chr.chr_def->uuid, buf),
557 ctxt->chr.def_handle,
558 ctxt->chr.val_handle);
559 break;
560
561 case BLE_GATT_REGISTER_OP_DSC:
562 MODLOG_DFLT(DEBUG, "registering descriptor %s with handle=%d\n",
563 ble_uuid_to_str(ctxt->dsc.dsc_def->uuid, buf),
564 ctxt->dsc.handle);
565 break;
566
567 default:
568 assert(0);
569 break;
570 }
571 }
572
573 void
gatt_svr_print_svcs(void)574 gatt_svr_print_svcs(void)
575 {
576 ble_gatts_show_local();
577 }
578
579 int
gatt_svr_init(void)580 gatt_svr_init(void)
581 {
582 int rc;
583
584 rc = ble_gatts_count_cfg(gatt_svr_svcs);
585 if (rc != 0) {
586 return rc;
587 }
588
589 rc = ble_gatts_add_svcs(gatt_svr_svcs);
590 if (rc != 0) {
591 return rc;
592 }
593
594 return 0;
595 }
596