3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2011 Nokia Corporation
6 * Copyright (C) 2011 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "lib/bluetooth.h"
36 static uint128_t bluetooth_base_uuid = {
37 .data = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
38 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
41 #define BASE_UUID16_OFFSET 2
42 #define BASE_UUID32_OFFSET 0
44 static void bt_uuid16_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
48 dst->value.u128 = bluetooth_base_uuid;
49 dst->type = BT_UUID128;
52 * No matter the system: 128-bit UUIDs should be stored
53 * as big-endian. 16-bit UUIDs are stored on host order.
56 be16 = htons(src->value.u16);
57 memcpy(&dst->value.u128.data[BASE_UUID16_OFFSET], &be16, sizeof(be16));
60 static void bt_uuid32_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
64 dst->value.u128 = bluetooth_base_uuid;
65 dst->type = BT_UUID128;
68 * No matter the system: 128-bit UUIDs should be stored
69 * as big-endian. 32-bit UUIDs are stored on host order.
72 be32 = htonl(src->value.u32);
73 memcpy(&dst->value.u128.data[BASE_UUID32_OFFSET], &be32, sizeof(be32));
76 void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
83 bt_uuid32_to_uuid128(src, dst);
86 bt_uuid16_to_uuid128(src, dst);
94 static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
96 return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
99 int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
101 memset(btuuid, 0, sizeof(bt_uuid_t));
102 btuuid->type = BT_UUID16;
103 btuuid->value.u16 = value;
108 int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
110 memset(btuuid, 0, sizeof(bt_uuid_t));
111 btuuid->type = BT_UUID32;
112 btuuid->value.u32 = value;
117 int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
119 memset(btuuid, 0, sizeof(bt_uuid_t));
120 btuuid->type = BT_UUID128;
121 btuuid->value.u128 = value;
126 int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
130 bt_uuid_to_uuid128(uuid1, &u1);
131 bt_uuid_to_uuid128(uuid2, &u2);
133 return bt_uuid128_cmp(&u1, &u2);
137 * convert the UUID to string, copying a maximum of n characters.
139 int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
143 unsigned short data1;
144 unsigned short data2;
145 unsigned short data3;
147 unsigned short data5;
150 if (!uuid || uuid->type == BT_UUID_UNSPEC) {
151 snprintf(str, n, "NULL");
155 /* Convert to 128 Bit format */
156 bt_uuid_to_uuid128(uuid, &tmp);
157 data = (uint8_t *) &tmp.value.u128;
159 memcpy(&data0, &data[0], 4);
160 memcpy(&data1, &data[4], 2);
161 memcpy(&data2, &data[6], 2);
162 memcpy(&data3, &data[8], 2);
163 memcpy(&data4, &data[10], 4);
164 memcpy(&data5, &data[14], 2);
166 snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
167 ntohl(data0), ntohs(data1),
168 ntohs(data2), ntohs(data3),
169 ntohl(data4), ntohs(data5));
174 static inline int is_uuid128(const char *string)
176 return (strlen(string) == 36 &&
183 static inline int is_base_uuid128(const char *string)
188 if (!is_uuid128(string))
191 return sscanf(string,
192 "0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]",
193 &uuid, &dummy, &dummy, &dummy, &dummy) == 5;
196 static inline int is_uuid32(const char *string)
198 return (strlen(string) == 8 || strlen(string) == 10);
201 static inline int is_uuid16(const char *string)
203 return (strlen(string) == 4 || strlen(string) == 6);
206 static int bt_string_to_uuid16(bt_uuid_t *uuid, const char *string)
211 u16 = strtol(string, &endptr, 16);
212 if (endptr && (*endptr == '\0' || *endptr == '-')) {
213 bt_uuid16_create(uuid, u16);
220 static int bt_string_to_uuid32(bt_uuid_t *uuid, const char *string)
225 u32 = strtol(string, &endptr, 16);
226 if (endptr && *endptr == '\0') {
227 bt_uuid32_create(uuid, u32);
234 static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string)
236 uint32_t data0, data4;
237 uint16_t data1, data2, data3, data5;
239 uint8_t *val = (uint8_t *) &u128;
241 if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
242 &data0, &data1, &data2,
243 &data3, &data4, &data5) != 6)
246 data0 = htonl(data0);
247 data1 = htons(data1);
248 data2 = htons(data2);
249 data3 = htons(data3);
250 data4 = htonl(data4);
251 data5 = htons(data5);
253 memcpy(&val[0], &data0, 4);
254 memcpy(&val[4], &data1, 2);
255 memcpy(&val[6], &data2, 2);
256 memcpy(&val[8], &data3, 2);
257 memcpy(&val[10], &data4, 4);
258 memcpy(&val[14], &data5, 2);
260 bt_uuid128_create(uuid, u128);
265 int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
267 if (is_base_uuid128(string))
268 return bt_string_to_uuid16(uuid, string + 4);
269 else if (is_uuid128(string))
270 return bt_string_to_uuid128(uuid, string);
271 else if (is_uuid32(string))
272 return bt_string_to_uuid32(uuid, string);
273 else if (is_uuid16(string))
274 return bt_string_to_uuid16(uuid, string);
279 int bt_uuid_strcmp(const void *a, const void *b)
283 bt_string_to_uuid(&u1, a);
284 bt_string_to_uuid(&u2, b);
286 return bt_uuid_cmp(&u1, &u2);
289 int bt_uuid_to_le(const bt_uuid_t *src, void *dst)
295 bt_put_le16(src->value.u16, dst);
298 bt_uuid32_to_uuid128(src, &uuid);
302 /* Convert from 128-bit BE to LE */
303 bswap_128(&src->value.u128, dst);