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