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 <stddef.h>
21 #include <string.h>
22 #include "securec.h"
23 #include "host/ble_uuid.h"
24 #include "nimble/ble.h"
25 #include "ble_hs_priv.h"
26
27 static const ble_uuid_t *uuid_ccc =
28 BLE_UUID16_DECLARE(BLE_GATT_DSC_CLT_CFG_UUID16);
29
30 static const char *const ble_gatt_chr_f_names[] = {
31 "BROADCAST",
32 "READ",
33 "WRITE_NO_RSP",
34 "WRITE",
35 "NOTIFY",
36 "INDICATE",
37 "AUTH_SIGN_WRITE",
38 "RELIABLE_WRITE",
39 "AUX_WRITE",
40 "READ_ENC",
41 "READ_AUTHEN",
42 "READ_AUTHOR",
43 "WRITE_ENC",
44 "WRITE_AUTHEN",
45 "WRITE_AUTHOR",
46 NULL
47 };
48
49 static const char *const ble_gatt_dsc_f_names[] = {
50 "READ",
51 "WRITE",
52 "READ_ENC",
53 "READ_AUTHEN",
54 "READ_AUTHOR",
55 "WRITE_ENC",
56 "WRITE_AUTHEN",
57 "WRITE_AUTHOR",
58 NULL
59 };
60
61 #define BLE_CHR_FLAGS_STR_LEN 180
62
ble_gatts_flags_to_str(uint16_t flags,char * buf,const char * const * names)63 static char *ble_gatts_flags_to_str(uint16_t flags, char *buf, const char *const *names)
64 {
65 int bit;
66 bool non_empty = false;
67 size_t length = 0;
68 buf[0] = '\0';
69 strcpy_s(buf, sizeof(buf), "[");
70 length += 1;
71
72 for (bit = 0; names[bit]; ++bit) {
73 if (flags & (1 << bit)) {
74 length += strlen(names[bit]);
75 if (length + 1 >= BLE_CHR_FLAGS_STR_LEN) {
76 return buf;
77 }
78
79 if (non_empty) {
80 strcat_s(buf, sizeof(buf), "|");
81 length += 1;
82 }
83
84 strcat_s(buf, sizeof(buf), names[bit]);
85 non_empty = true;
86 }
87 }
88
89 strcat_s(buf, sizeof(buf), "]");
90 return buf;
91 }
92
93 #define STRINGIFY(X) #X
94 #define FIELD_NAME_LEN STRINGIFY(12)
95 #define FIELD_INDENT STRINGIFY(2)
96
ble_gatt_show_local_chr(const struct ble_gatt_svc_def * svc,uint16_t handle,char * uuid_buf,char * flags_buf)97 static void ble_gatt_show_local_chr(const struct ble_gatt_svc_def *svc,
98 uint16_t handle, char *uuid_buf, char *flags_buf)
99 {
100 const struct ble_gatt_chr_def *chr;
101 const struct ble_gatt_dsc_def *dsc;
102
103 for (chr = svc->characteristics; chr && chr->uuid; ++chr) {
104 printf("characteristic\n");
105 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
106 "%s\n", " ", "uuid",
107 ble_uuid_to_str(chr->uuid, uuid_buf));
108 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
109 "%d\n", " ", "def_handle", handle);
110 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
111 "%d\n", " ", "val_handle", handle + 1);
112 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
113 "%d\n", " ", "min_key_size", chr->min_key_size);
114 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
115 "%s\n", " ", "flags",
116 ble_gatts_flags_to_str(chr->flags,
117 flags_buf, ble_gatt_chr_f_names));
118 handle += 2;
119
120 if ((chr->flags & BLE_GATT_CHR_F_NOTIFY) ||
121 (chr->flags & BLE_GATT_CHR_F_INDICATE)) {
122 printf("ccc descriptor\n");
123 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
124 "%s\n", " ", "uuid",
125 ble_uuid_to_str(uuid_ccc, uuid_buf));
126 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
127 "%d\n", " ", "handle", handle);
128 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
129 "%d\n", " ", "min_key_size", 0);
130 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
131 "%s\n", " ", "flags",
132 ble_gatts_flags_to_str(BLE_ATT_F_READ | BLE_ATT_F_WRITE,
133 flags_buf, ble_gatt_dsc_f_names));
134 handle++;
135 }
136
137 for (dsc = chr->descriptors; dsc && dsc->uuid; ++dsc) {
138 printf("descriptor\n");
139 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
140 "%s\n", " ", "uuid",
141 ble_uuid_to_str(dsc->uuid, uuid_buf));
142 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
143 "%d\n", " ", "handle", handle);
144 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
145 "%d\n", " ", "min_key_size", dsc->min_key_size);
146 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
147 "%s\n", " ", "flags",
148 ble_gatts_flags_to_str(dsc->att_flags,
149 flags_buf, ble_gatt_dsc_f_names));
150 handle++;
151 }
152 }
153 }
154
ble_gatt_show_local_inc_svc(const struct ble_gatt_svc_def * svc,uint16_t handle,char * uuid_buf)155 static int ble_gatt_show_local_inc_svc(const struct ble_gatt_svc_def *svc,
156 uint16_t handle, char *uuid_buf)
157 {
158 const struct ble_gatt_svc_def **includes;
159 int num = 0;
160
161 for (includes = &svc->includes[0]; *includes != NULL; ++includes) {
162 printf("included service\n");
163 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
164 "%s\n", " ", "uuid",
165 ble_uuid_to_str((*includes)->uuid, uuid_buf));
166 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
167 "%d\n", " ", "attr handle", handle);
168 ++num;
169 }
170
171 return num;
172 }
173
ble_gatt_show_local_svc(const struct ble_gatt_svc_def * svc,uint16_t handle,uint16_t end_group_handle,void * arg)174 static void ble_gatt_show_local_svc(const struct ble_gatt_svc_def *svc,
175 uint16_t handle, uint16_t end_group_handle,
176 void *arg)
177 {
178 uint16_t handle_tmp = handle;
179 char uuid_buf[BLE_UUID_STR_LEN];
180 char flags_buf[BLE_CHR_FLAGS_STR_LEN];
181 printf("%s service\n",
182 svc->type == BLE_GATT_SVC_TYPE_PRIMARY ?
183 "primary" : "secondary");
184 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
185 "%s\n", " ", "uuid",
186 ble_uuid_to_str(svc->uuid, uuid_buf));
187 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
188 "%d\n", " ", "handle",
189 handle_tmp);
190 printf("%" FIELD_INDENT "s %" FIELD_NAME_LEN "s "
191 "%d\n", " ", "end_handle",
192 end_group_handle);
193 handle_tmp++;
194
195 if (svc->includes) {
196 handle_tmp += ble_gatt_show_local_inc_svc(svc, handle_tmp, uuid_buf);
197 }
198
199 ble_gatt_show_local_chr(svc, handle_tmp,
200 uuid_buf, flags_buf);
201 }
202
ble_gatts_show_local(void)203 void ble_gatts_show_local(void)
204 {
205 ble_gatts_lcl_svc_foreach(ble_gatt_show_local_svc, NULL);
206 }