1 #include "common/bt_target.h"
2 #include "osi/allocator.h"
3
4 #include <string.h>
5 #include "gatt_int.h"
6 #include "stack/l2c_api.h"
7 #include "l2c_int.h"
8 #include "smp_int.h"
9
10 #if (BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE)
11
12 const char *const gatt_attr_name[] = {
13 "primary service",
14 "secondary service",
15 "included service",
16 "characteristic",
17 };
18
19 const char *const gatt_char_desc_name[] = {
20 "characteristic extended properties",
21 "characteristic user description",
22 "client characteristic configuration",
23 "server characteristic configuration",
24 "characteristic presentation format",
25 "characteristic aggregate format",
26 };
27
gatt_get_attr_name(UINT16 uuid)28 static const char *gatt_get_attr_name(UINT16 uuid)
29 {
30 if (uuid >= GATT_UUID_PRI_SERVICE && uuid <= GATT_UUID_CHAR_DECLARE) {
31 return gatt_attr_name[uuid - GATT_UUID_PRI_SERVICE];
32 }
33
34 if (uuid >= GATT_UUID_CHAR_EXT_PROP && uuid <= GATT_UUID_CHAR_AGG_FORMAT) {
35 return gatt_char_desc_name[uuid - GATT_UUID_CHAR_EXT_PROP];
36 }
37
38 return "Unknown Attribute";
39 }
40
attr_uuid_to_bt_uuid(void * p_attr,tBT_UUID * p_uuid)41 static void attr_uuid_to_bt_uuid(void *p_attr, tBT_UUID *p_uuid)
42 {
43 tGATT_ATTR16 *p_attr16 = (tGATT_ATTR16 *)p_attr;
44
45 if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_16) {
46 p_uuid->len = LEN_UUID_16;
47 p_uuid->uu.uuid16 = p_attr16->uuid;
48 } else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_32) {
49 tGATT_ATTR32 *p_attr32 = (tGATT_ATTR32 *)p_attr;
50 p_uuid->len = LEN_UUID_32;
51 p_uuid->uu.uuid32 = p_attr32->uuid;
52 } else if (p_attr16->uuid_type == GATT_ATTR_UUID_TYPE_128) {
53 tGATT_ATTR128 *p_attr128 = (tGATT_ATTR128 *)p_attr;
54 p_uuid->len = LEN_UUID_128;
55 memcpy(p_uuid->uu.uuid128, p_attr128->uuid, LEN_UUID_128);
56 }
57 }
58
calculate_database_info_size(void)59 static size_t calculate_database_info_size(void)
60 {
61 UINT8 i;
62 tGATT_SVC_DB *p_db;
63 tGATT_ATTR16 *p_attr;
64 size_t len = 0;
65
66 for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
67 p_db = gatt_cb.sr_reg[i].p_db;
68 if (p_db && p_db->p_attr_list) {
69 p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
70 while (p_attr) {
71 if (p_attr->uuid == GATT_UUID_PRI_SERVICE ||
72 p_attr->uuid == GATT_UUID_SEC_SERVICE) {
73 // Service declaration
74 len += 4 + p_attr->p_value->uuid.len;
75 } else if (p_attr->uuid == GATT_UUID_INCLUDE_SERVICE) {
76 // Included service declaration
77 len += 8 + p_attr->p_value->incl_handle.service_type.len;
78 } else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
79 tBT_UUID char_uuid = {0};
80 // Characteristic declaration
81 p_attr = (tGATT_ATTR16 *)p_attr->p_next;
82 attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
83 // Increment 1 to fetch characteristic uuid from value declaration attribute
84 len += 7 + char_uuid.len;
85 } else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
86 p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
87 p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG ||
88 p_attr->uuid == GATT_UUID_CHAR_PRESENT_FORMAT ||
89 p_attr->uuid == GATT_UUID_CHAR_AGG_FORMAT) {
90 // Descriptor
91 len += 4;
92 } else if (p_attr->uuid == GATT_UUID_CHAR_EXT_PROP) {
93 // Descriptor
94 len += 6;
95 }
96 p_attr = (tGATT_ATTR16 *) p_attr->p_next;
97 }
98 }
99 }
100
101 return len;
102 }
103
fill_database_info(UINT8 * p_data)104 static void fill_database_info(UINT8 *p_data)
105 {
106 UINT8 i;
107 tGATT_SVC_DB *p_db;
108 tGATT_ATTR16 *p_attr;
109
110 for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
111 p_db = gatt_cb.sr_reg[i].p_db;
112 if (p_db && p_db->p_attr_list) {
113 p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
114 while (p_attr) {
115 if (p_attr->uuid == GATT_UUID_PRI_SERVICE ||
116 p_attr->uuid == GATT_UUID_SEC_SERVICE) {
117 // Service declaration
118 UINT16_TO_STREAM(p_data, p_attr->handle);
119 UINT16_TO_STREAM(p_data, p_attr->uuid);
120 gatt_build_uuid_to_stream(&p_data, p_attr->p_value->uuid);
121 } else if (p_attr->uuid == GATT_UUID_INCLUDE_SERVICE) {
122 // Included service declaration
123 UINT16_TO_STREAM(p_data, p_attr->handle);
124 UINT16_TO_STREAM(p_data, GATT_UUID_INCLUDE_SERVICE);
125 UINT16_TO_STREAM(p_data, p_attr->p_value->incl_handle.s_handle);
126 UINT16_TO_STREAM(p_data, p_attr->p_value->incl_handle.e_handle);
127 gatt_build_uuid_to_stream(&p_data, p_attr->p_value->incl_handle.service_type);
128 } else if (p_attr->uuid == GATT_UUID_CHAR_DECLARE) {
129 tBT_UUID char_uuid = {0};
130 // Characteristic declaration
131 UINT16_TO_STREAM(p_data, p_attr->handle);
132 UINT16_TO_STREAM(p_data, GATT_UUID_CHAR_DECLARE);
133 UINT8_TO_STREAM(p_data, p_attr->p_value->char_decl.property);
134 UINT16_TO_STREAM(p_data, p_attr->p_value->char_decl.char_val_handle);
135 p_attr = (tGATT_ATTR16 *)p_attr->p_next;
136 attr_uuid_to_bt_uuid((void *)p_attr, &char_uuid);
137 // Increment 1 to fetch characteristic uuid from value declaration attribute
138 gatt_build_uuid_to_stream(&p_data, char_uuid);
139 } else if (p_attr->uuid == GATT_UUID_CHAR_DESCRIPTION ||
140 p_attr->uuid == GATT_UUID_CHAR_CLIENT_CONFIG ||
141 p_attr->uuid == GATT_UUID_CHAR_SRVR_CONFIG ||
142 p_attr->uuid == GATT_UUID_CHAR_PRESENT_FORMAT ||
143 p_attr->uuid == GATT_UUID_CHAR_AGG_FORMAT) {
144 // Descriptor
145 UINT16_TO_STREAM(p_data, p_attr->handle);
146 UINT16_TO_STREAM(p_data, p_attr->uuid);
147 } else if (p_attr->uuid == GATT_UUID_CHAR_EXT_PROP) {
148 // Descriptor
149 UINT16_TO_STREAM(p_data, p_attr->handle);
150 UINT16_TO_STREAM(p_data, p_attr->uuid);
151 // TODO: process extended properties descriptor
152 if (p_attr->p_value->attr_val.attr_len == 2) {
153 memcpy(p_data, p_attr->p_value->attr_val.attr_val, 2);
154 } else {
155 UINT16_TO_STREAM(p_data, 0x0000);
156 }
157 }
158 p_attr = (tGATT_ATTR16 *) p_attr->p_next;
159 }
160 }
161 }
162 }
163
gatts_calculate_datebase_hash(BT_OCTET16 hash)164 tGATT_STATUS gatts_calculate_datebase_hash(BT_OCTET16 hash)
165 {
166 UINT8 tmp;
167 UINT16 i;
168 UINT16 j;
169 size_t len;
170 UINT8 *data_buf = NULL;
171
172 len = calculate_database_info_size();
173
174 data_buf = (UINT8 *)osi_malloc(len);
175 if (data_buf == NULL) {
176 GATT_TRACE_ERROR ("%s failed to allocate buffer (%u)\n", __func__, len);
177 return GATT_NO_RESOURCES;
178 }
179
180 fill_database_info(data_buf);
181
182 // reverse database info
183 for (i = 0, j = len-1; i < j; i++, j--) {
184 tmp = data_buf[i];
185 data_buf[i] = data_buf[j];
186 data_buf[j] = tmp;
187 }
188
189 #if SMP_INCLUDED == TRUE
190 BT_OCTET16 key = {0};
191 aes_cipher_msg_auth_code(key, data_buf, len, 16, hash);
192 //ESP_LOG_BUFFER_HEX("db hash", hash, BT_OCTET16_LEN);
193 #endif
194
195 osi_free(data_buf);
196 return GATT_SUCCESS;
197 }
198
gatts_show_local_database(void)199 void gatts_show_local_database(void)
200 {
201 UINT8 i;
202 tGATT_SVC_DB *p_db;
203 tGATT_ATTR16 *p_attr;
204
205 printf("\n================= GATTS DATABASE DUMP START =================\n");
206 for (i = 0; i < GATT_MAX_SR_PROFILES; i++) {
207 p_db = gatt_cb.sr_reg[i].p_db;
208 if (p_db && p_db->p_attr_list) {
209 p_attr = (tGATT_ATTR16 *)p_db->p_attr_list;
210 while (p_attr) {
211 switch (p_attr->uuid) {
212 case GATT_UUID_PRI_SERVICE:
213 case GATT_UUID_SEC_SERVICE:
214 // Service declaration
215 printf("%s\n", gatt_get_attr_name(p_attr->uuid));
216 printf("\tuuid %s\n", gatt_uuid_to_str(&p_attr->p_value->uuid));
217 printf("\thandle %d\n", p_attr->handle);
218 printf("\tend_handle %d\n",p_db->end_handle-1);
219 break;
220 case GATT_UUID_INCLUDE_SERVICE:
221 // Included service declaration
222 printf("%s\n", gatt_get_attr_name(p_attr->uuid));
223 printf("\tuuid %s\t", gatt_uuid_to_str(&p_attr->p_value->incl_handle.service_type));
224 printf("\thandle %d\n", p_attr->p_value->incl_handle.s_handle);
225 printf("\tend_handle %d\n", p_attr->p_value->incl_handle.e_handle);
226 break;
227 case GATT_UUID_CHAR_DECLARE: {
228 tBT_UUID char_uuid;
229 tGATT_ATTR16 *p_char_val;
230 p_char_val = (tGATT_ATTR16 *)p_attr->p_next;
231 attr_uuid_to_bt_uuid((void *)p_char_val, &char_uuid);
232
233 printf("%s\n", gatt_get_attr_name(p_attr->uuid));
234 printf("\tuuid %s\n", gatt_uuid_to_str(&char_uuid));
235 printf("\tdef_handle %d\n", p_attr->handle);
236 printf("\tval_handle %d\n", p_attr->p_value->char_decl.char_val_handle);
237 printf("\tperm 0x%04x, prop 0x%02x\n", p_char_val->permission, p_attr->p_value->char_decl.property);
238 break;
239 }
240 case GATT_UUID_CHAR_EXT_PROP:
241 case GATT_UUID_CHAR_DESCRIPTION:
242 case GATT_UUID_CHAR_CLIENT_CONFIG:
243 case GATT_UUID_CHAR_SRVR_CONFIG:
244 case GATT_UUID_CHAR_PRESENT_FORMAT:
245 case GATT_UUID_CHAR_AGG_FORMAT:
246 printf("%s\n", gatt_get_attr_name(p_attr->uuid));
247 printf("\thandle %d\n", p_attr->handle);
248 break;
249 }
250 p_attr = (tGATT_ATTR16 *) p_attr->p_next;
251 }
252 }
253 }
254 printf("================= GATTS DATABASE DUMP END =================\n");
255 }
256 #endif /* BLE_INCLUDED == TRUE && GATTS_INCLUDED == TRUE */
257