xref: /nrf52832-nimble/packages/NimBLE-latest/apps/btshell/src/gatt_svr.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 <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