1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "btm_wl.h"
17
18 #include <securec.h>
19
20 #include "hci/hci.h"
21 #include "platform/include/allocator.h"
22 #include "platform/include/list.h"
23 #include "platform/include/mutex.h"
24
25 #include "btm.h"
26 #include "btm_controller.h"
27
28 #define STATUS_NONE 0
29 #define STATUS_INITIALIZED 1
30
31 #define IS_INITIALIZED() (g_status == STATUS_INITIALIZED)
32
33 typedef struct {
34 uint8_t addressType;
35 BtAddr address;
36 } BtmWhiteListEntity;
37
38 static List *g_whiteList = NULL;
39 static Mutex *g_whiteListLock = NULL;
40 static uint8_t g_whiteListSize = 0;
41
42 static uint8_t g_status = STATUS_NONE;
43
BtmAllocWhiteListEntity(uint8_t addressType,const BtAddr * address)44 static BtmWhiteListEntity *BtmAllocWhiteListEntity(uint8_t addressType, const BtAddr *address)
45 {
46 BtmWhiteListEntity *entity = MEM_MALLOC.alloc(sizeof(BtmWhiteListEntity));
47 if (entity != NULL) {
48 entity->addressType = addressType;
49 entity->address = *address;
50 }
51 return entity;
52 }
53
BtmFreeWhiteListEntity(void * entity)54 static void BtmFreeWhiteListEntity(void *entity)
55 {
56 MEM_MALLOC.free(entity);
57 }
58
BtmFindWhiteListEntityByType(uint8_t addressType)59 static BtmWhiteListEntity *BtmFindWhiteListEntityByType(uint8_t addressType)
60 {
61 BtmWhiteListEntity *entity = NULL;
62
63 ListNode *node = ListGetFirstNode(g_whiteList);
64 while (node != NULL) {
65 entity = ListGetNodeData(node);
66 if (entity->addressType == addressType) {
67 break;
68 } else {
69 entity = NULL;
70 }
71 node = ListGetNextNode(node);
72 }
73
74 return entity;
75 }
76
IsSameAddress(const BtAddr * addr1,const BtAddr * addr2)77 static bool IsSameAddress(const BtAddr *addr1, const BtAddr *addr2)
78 {
79 bool isSame = true;
80 for (uint8_t i = 0; i < BT_ADDRESS_SIZE; i++) {
81 if (addr1->addr[i] != addr2->addr[i]) {
82 isSame = false;
83 }
84 }
85 return isSame;
86 }
87
BtmFindWhiteListEntity(uint8_t addressType,const BtAddr * address)88 static BtmWhiteListEntity *BtmFindWhiteListEntity(uint8_t addressType, const BtAddr *address)
89 {
90 BtmWhiteListEntity *entity = NULL;
91
92 ListNode *node = ListGetFirstNode(g_whiteList);
93 while (node != NULL) {
94 entity = ListGetNodeData(node);
95 if ((entity->addressType == addressType) && IsSameAddress(&entity->address, address)) {
96 break;
97 } else {
98 entity = NULL;
99 }
100 node = ListGetNextNode(node);
101 }
102
103 return entity;
104 }
105
BtmAddDeviceToWhiteList(uint8_t addressType,const BtAddr * address)106 int BtmAddDeviceToWhiteList(uint8_t addressType, const BtAddr *address)
107 {
108 if (!IS_INITIALIZED()) {
109 return BT_BAD_STATUS;
110 }
111
112 MutexLock(g_whiteListLock);
113 BtmWhiteListEntity *entity = NULL;
114 if (addressType == WHITE_LIST_ADDRESS_TYPE_ANONYMOUS_ADVERTISEMENTS) {
115 entity = BtmFindWhiteListEntityByType(WHITE_LIST_ADDRESS_TYPE_ANONYMOUS_ADVERTISEMENTS);
116 if (entity != NULL) {
117 MutexUnlock(g_whiteListLock);
118 return BT_BAD_STATUS;
119 }
120 } else {
121 entity = BtmFindWhiteListEntity(addressType, address);
122 if (entity != NULL) {
123 MutexUnlock(g_whiteListLock);
124 return BT_BAD_STATUS;
125 }
126 }
127
128 if (ListGetSize(g_whiteList) >= g_whiteListSize) {
129 MutexUnlock(g_whiteListLock);
130 return BT_OPERATION_FAILED;
131 }
132
133 entity = BtmAllocWhiteListEntity(addressType, address);
134 if (entity == NULL) {
135 MutexUnlock(g_whiteListLock);
136 return BT_NO_MEMORY;
137 }
138
139 ListAddLast(g_whiteList, entity);
140
141 MutexUnlock(g_whiteListLock);
142
143 HciLeAddDeviceToWhiteListParam cmdParam = {
144 .addressType = addressType,
145 .address =
146 {
147 .raw = {0},
148 },
149 };
150 (void)memcpy_s(cmdParam.address.raw, BT_ADDRESS_SIZE, address, BT_ADDRESS_SIZE);
151
152 HCI_LeAddDeviceToWhiteList(&cmdParam);
153
154 return BT_SUCCESS;
155 }
156
BtmRemoveDeviceFromWhiteList(uint8_t addressType,const BtAddr * address)157 void BtmRemoveDeviceFromWhiteList(uint8_t addressType, const BtAddr *address)
158 {
159 if (!IS_INITIALIZED()) {
160 return;
161 }
162
163 bool removed = false;
164
165 MutexLock(g_whiteListLock);
166
167 BtmWhiteListEntity *entity = NULL;
168 ListNode *node = ListGetFirstNode(g_whiteList);
169 while (node != NULL) {
170 entity = ListGetNodeData(node);
171 if (entity->addressType == addressType) {
172 if (addressType == WHITE_LIST_ADDRESS_TYPE_ANONYMOUS_ADVERTISEMENTS) {
173 ListRemoveNode(g_whiteList, entity);
174 removed = true;
175 break;
176 }
177 if (IsSameAddress(&entity->address, address)) {
178 ListRemoveNode(g_whiteList, entity);
179 removed = true;
180 break;
181 }
182 }
183 node = ListGetNextNode(node);
184 }
185
186 MutexUnlock(g_whiteListLock);
187
188 if (removed) {
189 HciLeRemoveDeviceFromWhiteListParam cmdParam = {
190 .addressType = addressType,
191 .address =
192 {
193 .raw = {0},
194 },
195 };
196 (void)memcpy_s(cmdParam.address.raw, BT_ADDRESS_SIZE, address, BT_ADDRESS_SIZE);
197 HCI_LeRemoveDeviceFromWhiteList(&cmdParam);
198 }
199 }
200
BtmClearWhiteList()201 void BtmClearWhiteList()
202 {
203 if (!IS_INITIALIZED()) {
204 return;
205 }
206
207 MutexLock(g_whiteListLock);
208
209 ListClear(g_whiteList);
210
211 MutexUnlock(g_whiteListLock);
212
213 HCI_LeClearWhiteList();
214 }
215
BtmGetDeviceCountInWhiteList()216 int BtmGetDeviceCountInWhiteList()
217 {
218 if (!IS_INITIALIZED()) {
219 return 0;
220 }
221
222 MutexLock(g_whiteListLock);
223
224 int deviceCount = ListGetSize(g_whiteList);
225
226 MutexUnlock(g_whiteListLock);
227
228 return deviceCount;
229 }
230
BtmInitWhiteList()231 void BtmInitWhiteList()
232 {
233 g_whiteList = ListCreate(BtmFreeWhiteListEntity);
234 g_whiteListLock = MutexCreate();
235
236 g_status = STATUS_INITIALIZED;
237 }
238
BtmCloseWhiteList()239 void BtmCloseWhiteList()
240 {
241 g_status = STATUS_NONE;
242
243 if (g_whiteListLock != NULL) {
244 MutexDelete(g_whiteListLock);
245 g_whiteListLock = NULL;
246 }
247
248 if (g_whiteList != NULL) {
249 ListDelete(g_whiteList);
250 g_whiteList = NULL;
251 }
252 }
253
BtmStartWhiteList()254 void BtmStartWhiteList()
255 {
256 uint8_t whiteListSize = 0;
257 int result = BtmGetWhiteListSize(&whiteListSize);
258 if (result == BT_SUCCESS) {
259 g_whiteListSize = whiteListSize;
260 }
261
262 HCI_LeClearWhiteList();
263 }
264
BtmStopWhiteList()265 void BtmStopWhiteList()
266 {
267 MutexLock(g_whiteListLock);
268 ListClear(g_whiteList);
269 MutexUnlock(g_whiteListLock);
270 }
271
BtmIsDeviceInWhiteList(uint8_t addressType,const BtAddr * address)272 bool BtmIsDeviceInWhiteList(uint8_t addressType, const BtAddr *address)
273 {
274 bool inWhiteList = false;
275 MutexLock(g_whiteListLock);
276 BtmWhiteListEntity *entity = NULL;
277 ListNode *node = ListGetFirstNode(g_whiteList);
278 while (node != NULL) {
279 entity = ListGetNodeData(node);
280 if (entity != NULL && (entity->addressType == addressType) && IsSameAddress(&entity->address, address)) {
281 inWhiteList = true;
282 break;
283 }
284 node = ListGetNextNode(node);
285 }
286 MutexUnlock(g_whiteListLock);
287 return inWhiteList;
288 }