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 <stdint.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <stdio.h>
25 #include "securec.h"
26 #include "os/os_mbuf.h"
27 #include "nimble/ble.h"
28 #include "ble_hs_priv.h"
29 #include "host/ble_uuid.h"
30
31 static uint8_t ble_uuid_base[16] = {
32 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
33 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
34 };
35
36 #if MYNEWT_VAL(BLE_HS_DEBUG)
37 #define VERIFY_UUID(uuid) \
38 assert((uuid->type == BLE_UUID_TYPE_16) || \
39 (uuid->type == BLE_UUID_TYPE_32) || \
40 (uuid->type == BLE_UUID_TYPE_128))
41 #else
42 #define VERIFY_UUID(uuid)
43 #endif
44
ble_uuid_init_from_buf(ble_uuid_any_t * uuid,const void * buf,size_t len)45 int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len)
46 {
47 switch (len) {
48 case 2: // 2:case value
49 uuid->u.type = BLE_UUID_TYPE_16;
50 uuid->u16.value = get_le16(buf);
51 return 0;
52
53 case 4: // 4:case value
54 uuid->u.type = BLE_UUID_TYPE_32;
55 uuid->u32.value = get_le32(buf);
56 return 0;
57
58 case 16: // 16:case value
59 uuid->u.type = BLE_UUID_TYPE_128;
60 memcpy_s(uuid->u128.value, sizeof(uuid->u128.value), buf, 16); // 16:size
61 return 0;
62 default:
63 break;
64 }
65
66 return BLE_HS_EINVAL;
67 }
68
ble_uuid_cmp(const ble_uuid_t * uuid1,const ble_uuid_t * uuid2)69 int ble_uuid_cmp(const ble_uuid_t *uuid1, const ble_uuid_t *uuid2)
70 {
71 VERIFY_UUID(uuid1);
72 VERIFY_UUID(uuid2);
73
74 if (uuid1->type != uuid2->type) {
75 return uuid1->type - uuid2->type;
76 }
77
78 switch (uuid1->type) {
79 case BLE_UUID_TYPE_16:
80 return (int) BLE_UUID16(uuid1)->value - (int) BLE_UUID16(uuid2)->value;
81
82 case BLE_UUID_TYPE_32:
83 return (int) BLE_UUID32(uuid1)->value - (int) BLE_UUID32(uuid2)->value;
84
85 case BLE_UUID_TYPE_128:
86 return memcmp(BLE_UUID128(uuid1)->value, BLE_UUID128(uuid2)->value, 16); // 16:size
87
88 default:
89 break;
90 }
91
92 BLE_HS_DBG_ASSERT(0);
93 return -1;
94 }
95
ble_uuid_copy(ble_uuid_any_t * dst,const ble_uuid_t * src)96 void ble_uuid_copy(ble_uuid_any_t *dst, const ble_uuid_t *src)
97 {
98 VERIFY_UUID(src);
99
100 switch (src->type) {
101 case BLE_UUID_TYPE_16:
102 dst->u16 = *(const ble_uuid16_t *)src;
103 break;
104
105 case BLE_UUID_TYPE_32:
106 dst->u32 = *(const ble_uuid32_t *)src;
107 break;
108
109 case BLE_UUID_TYPE_128:
110 dst->u128 = *(const ble_uuid128_t *)src;
111 break;
112
113 default:
114 BLE_HS_DBG_ASSERT(0);
115 break;
116 }
117 }
118
ble_uuid_to_str(const ble_uuid_t * uuid,char * dst)119 char *ble_uuid_to_str(const ble_uuid_t *uuid, char *dst)
120 {
121 const uint8_t *u8p;
122
123 switch (uuid->type) {
124 case BLE_UUID_TYPE_16:
125 sprintf_s(dst, sizeof(*dst), "0x%04x", BLE_UUID16(uuid)->value);
126 break;
127
128 case BLE_UUID_TYPE_32:
129 sprintf_s(dst, sizeof(*dst), "0x%08x", BLE_UUID32(uuid)->value);
130 break;
131
132 case BLE_UUID_TYPE_128:
133 u8p = BLE_UUID128(uuid)->value;
134 sprintf_s(dst, sizeof(*dst), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
135 "%02x%02x%02x%02x%02x%02x",
136 u8p[15], u8p[14], // 15:array element, 14:array element
137 u8p[13], u8p[12], // 13:array element, 12:array element
138 u8p[11], u8p[10], // 11:array element, 10:array element
139 u8p[9], u8p[8], // 9:array element, 9:array element
140 u8p[7], u8p[6], // 7:array element, 6:array element
141 u8p[5], u8p[4], // 5:array element, 4:array element
142 u8p[3], u8p[2], // 3:array element, 2:array element
143 u8p[1], u8p[0]);
144 break;
145
146 default:
147 dst[0] = '\0';
148 break;
149 }
150
151 return dst;
152 }
153
ble_uuid_u16(const ble_uuid_t * uuid)154 uint16_t ble_uuid_u16(const ble_uuid_t *uuid)
155 {
156 VERIFY_UUID(uuid);
157 return uuid->type == BLE_UUID_TYPE_16 ? BLE_UUID16(uuid)->value : 0;
158 }
159
160 /* APIs below are private (ble_uuid_priv.h) */
161
ble_uuid_init_from_att_mbuf(ble_uuid_any_t * uuid,struct os_mbuf * om,int off,int len)162 int ble_uuid_init_from_att_mbuf(ble_uuid_any_t *uuid, struct os_mbuf *om, int off, int len)
163 {
164 uint8_t val[16];
165 int rc;
166 rc = os_mbuf_copydata(om, off, len, val);
167 if (rc != 0) {
168 return rc;
169 }
170
171 rc = ble_uuid_init_from_att_buf(uuid, val, len);
172 return rc;
173 }
174
ble_uuid_init_from_att_buf(ble_uuid_any_t * uuid,const void * buf,size_t len)175 int ble_uuid_init_from_att_buf(ble_uuid_any_t *uuid, const void *buf, size_t len)
176 {
177 int rc = 0;
178
179 if (len == 2) { // 2:Analyzing conditions
180 uuid->u.type = BLE_UUID_TYPE_16;
181 uuid->u16.value = get_le16(buf);
182 } else if (len == 16) { // 16:Analyzing conditions
183 uuid->u.type = BLE_UUID_TYPE_128;
184 memcpy_s(uuid->u128.value, sizeof(uuid->u128.value), buf, 16); // 16:size
185 } else {
186 rc = BLE_HS_EINVAL;
187 }
188
189 return rc;
190 }
191
ble_uuid_to_any(const ble_uuid_t * uuid,ble_uuid_any_t * uuid_any)192 int ble_uuid_to_any(const ble_uuid_t *uuid, ble_uuid_any_t *uuid_any)
193 {
194 VERIFY_UUID(uuid);
195 uuid_any->u.type = uuid->type;
196
197 switch (uuid->type) {
198 case BLE_UUID_TYPE_16:
199 uuid_any->u16.value = BLE_UUID16(uuid)->value;
200 break;
201
202 case BLE_UUID_TYPE_32:
203 uuid_any->u32.value = BLE_UUID32(uuid)->value;
204 break;
205
206 case BLE_UUID_TYPE_128:
207 memcpy_s(uuid_any->u128.value, sizeof(uuid_any->u128.value), BLE_UUID128(uuid)->value, 16); // 16:size
208 break;
209
210 default:
211 break;
212 }
213
214 return 0;
215 }
216
ble_uuid_to_mbuf(const ble_uuid_t * uuid,struct os_mbuf * om)217 int ble_uuid_to_mbuf(const ble_uuid_t *uuid, struct os_mbuf *om)
218 {
219 int len;
220 void *buf;
221 VERIFY_UUID(uuid);
222 len = ble_uuid_length(uuid);
223 buf = os_mbuf_extend(om, len);
224 if (buf == NULL) {
225 return BLE_HS_ENOMEM;
226 }
227
228 ble_uuid_flat(uuid, buf);
229 return 0;
230 }
231
ble_uuid_flat(const ble_uuid_t * uuid,void * dst)232 int ble_uuid_flat(const ble_uuid_t *uuid, void *dst)
233 {
234 VERIFY_UUID(uuid);
235
236 switch (uuid->type) {
237 case BLE_UUID_TYPE_16:
238 put_le16(dst, BLE_UUID16(uuid)->value);
239 break;
240
241 case BLE_UUID_TYPE_32:
242 memcpy_s(dst, sizeof(*dst), ble_uuid_base, 16); // 16:size
243 put_le32((uint8_t *)dst + 12, BLE_UUID32(uuid)->value); // 12:byte alignment
244 break;
245
246 case BLE_UUID_TYPE_128:
247 memcpy_s(dst, sizeof(*dst), BLE_UUID128(uuid)->value, 16); // 16:size
248 break;
249
250 default:
251 return BLE_HS_EINVAL;
252 }
253
254 return 0;
255 }
256
ble_uuid_length(const ble_uuid_t * uuid)257 int ble_uuid_length(const ble_uuid_t *uuid)
258 {
259 VERIFY_UUID(uuid);
260 return uuid->type >> 3; // 3:byte alignment
261 }