1 /* uuid.c - Bluetooth UUID handling */
2 
3 /*
4  * Copyright (c) 2015-2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <string.h>
10 #include <bt_errno.h>
11 #include <misc/byteorder.h>
12 #include <misc/printk.h>
13 
14 #include <bluetooth/uuid.h>
15 
16 #define UUID_16_BASE_OFFSET 12
17 
18 /* TODO: Decide whether to continue using BLE format or switch to RFC 4122 */
19 
20 /* Base UUID : 0000[0000]-0000-1000-8000-00805F9B34FB
21  * 0x2800    : 0000[2800]-0000-1000-8000-00805F9B34FB
22  *  little endian 0x2800 : [00 28] -> no swapping required
23  *  big endian 0x2800    : [28 00] -> swapping required
24  */
25 static const struct bt_uuid_128 uuid128_base = {
26 	.uuid = { BT_UUID_TYPE_128 },
27 	.val = { BT_UUID_128_ENCODE(
28 		0x00000000, 0x0000, 0x1000, 0x8000, 0x00805F9B34FB) }
29 };
30 
uuid_to_uuid128(const struct bt_uuid * src,struct bt_uuid_128 * dst)31 static void uuid_to_uuid128(const struct bt_uuid *src, struct bt_uuid_128 *dst)
32 {
33 	switch (src->type) {
34 	case BT_UUID_TYPE_16:
35 		*dst = uuid128_base;
36 		sys_put_le16(BT_UUID_16(src)->val,
37 			     &dst->val[UUID_16_BASE_OFFSET]);
38 		return;
39 	case BT_UUID_TYPE_32:
40 		*dst = uuid128_base;
41 		sys_put_le32(BT_UUID_32(src)->val,
42 			     &dst->val[UUID_16_BASE_OFFSET]);
43 		return;
44 	case BT_UUID_TYPE_128:
45 		memcpy(dst, src, sizeof(*dst));
46 		return;
47 	}
48 }
49 
uuid128_cmp(const struct bt_uuid * u1,const struct bt_uuid * u2)50 static int uuid128_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
51 {
52 	struct bt_uuid_128 uuid1, uuid2;
53 
54 	uuid_to_uuid128(u1, &uuid1);
55 	uuid_to_uuid128(u2, &uuid2);
56 
57 	return memcmp(uuid1.val, uuid2.val, 16);
58 }
59 
bt_uuid_cmp(const struct bt_uuid * u1,const struct bt_uuid * u2)60 int bt_uuid_cmp(const struct bt_uuid *u1, const struct bt_uuid *u2)
61 {
62 	/* Convert to 128 bit if types don't match */
63 	if (u1->type != u2->type) {
64 		return uuid128_cmp(u1, u2);
65 	}
66 
67 	switch (u1->type) {
68 	case BT_UUID_TYPE_16:
69 		return (int)BT_UUID_16(u1)->val - (int)BT_UUID_16(u2)->val;
70 	case BT_UUID_TYPE_32:
71 		return (int)BT_UUID_32(u1)->val - (int)BT_UUID_32(u2)->val;
72 	case BT_UUID_TYPE_128:
73 		return memcmp(BT_UUID_128(u1)->val, BT_UUID_128(u2)->val, 16);
74 	}
75 
76 	return -EINVAL;
77 }
78 
bt_uuid_create(struct bt_uuid * uuid,const u8_t * data,u8_t data_len)79 bool bt_uuid_create(struct bt_uuid *uuid, const u8_t *data, u8_t data_len)
80 {
81 	/* Copy UUID from packet data/internal variable to internal bt_uuid */
82 	switch (data_len) {
83 	case 2:
84 		uuid->type = BT_UUID_TYPE_16;
85 		BT_UUID_16(uuid)->val = sys_get_le16(data);
86 		break;
87 	case 4:
88 		uuid->type = BT_UUID_TYPE_32;
89 		BT_UUID_32(uuid)->val = sys_get_le32(data);
90 		break;
91 	case 16:
92 		uuid->type = BT_UUID_TYPE_128;
93 		memcpy(&BT_UUID_128(uuid)->val, data, 16);
94 		break;
95 	default:
96 		return 0; // return false;
97 	}
98 	return 1; // return true;
99 }
100 
101 #if defined(CONFIG_BT_DEBUG)
bt_uuid_to_str(const struct bt_uuid * uuid,char * str,size_t len)102 void bt_uuid_to_str(const struct bt_uuid *uuid, char *str, size_t len)
103 {
104 	bt_u32_t tmp1, tmp5;
105 	u16_t tmp0, tmp2, tmp3, tmp4;
106 
107 	switch (uuid->type) {
108 	case BT_UUID_TYPE_16:
109 		snprintk(str, len, "%04x", BT_UUID_16(uuid)->val);
110 		break;
111 	case BT_UUID_TYPE_32:
112 		snprintk(str, len, "%08x", BT_UUID_32(uuid)->val);
113 		break;
114 	case BT_UUID_TYPE_128:
115 		memcpy(&tmp0, &BT_UUID_128(uuid)->val[0], sizeof(tmp0));
116 		memcpy(&tmp1, &BT_UUID_128(uuid)->val[2], sizeof(tmp1));
117 		memcpy(&tmp2, &BT_UUID_128(uuid)->val[6], sizeof(tmp2));
118 		memcpy(&tmp3, &BT_UUID_128(uuid)->val[8], sizeof(tmp3));
119 		memcpy(&tmp4, &BT_UUID_128(uuid)->val[10], sizeof(tmp4));
120 		memcpy(&tmp5, &BT_UUID_128(uuid)->val[12], sizeof(tmp5));
121 
122 		snprintk(str, len, "%08x-%04x-%04x-%04x-%08x%04x",
123 			 tmp5, tmp4, tmp3, tmp2, tmp1, tmp0);
124 		break;
125 	default:
126 		(void)memset(str, 0, len);
127 		return;
128 	}
129 
130 }
131 
bt_uuid_str(const struct bt_uuid * uuid)132 const char *bt_uuid_str(const struct bt_uuid *uuid)
133 {
134 	static char str[37];
135 
136 	bt_uuid_to_str(uuid, str, sizeof(str));
137 
138 	return str;
139 }
140 #endif /* CONFIG_BT_DEBUG */
141