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 }