1 /*
2  * Copyright (C) 2021-2022 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 "hci.h"
17 
18 #include "btm/btm_thread.h"
19 #include "btstack.h"
20 #include "log.h"
21 #include "packet.h"
22 #include "platform/include/allocator.h"
23 #include "platform/include/event.h"
24 #include "platform/include/module.h"
25 #include "platform/include/queue.h"
26 #include "platform/include/reactor.h"
27 #include "platform/include/semaphore.h"
28 #include "platform/include/thread.h"
29 
30 #include "acl/hci_acl.h"
31 #include "cmd/hci_cmd.h"
32 #include "evt/hci_evt.h"
33 #include "hdi_wrapper.h"
34 #include "hci_def.h"
35 #include "hci_failure.h"
36 #include "hci_internal.h"
37 #include "hci_vendor_if.h"
38 
39 #define HCI_TX_QUEUE_SIZE INT32_MAX
40 #define HCI_RX_QUEUE_SIZE INT32_MAX
41 
42 static BtHciCallbacks g_hdiCallacks;
43 
44 static Queue *g_hciTxQueue = NULL;
45 static Queue *g_hciRxQueue = NULL;
46 
47 static ReactorItem *g_hciTxReactorItem = NULL;
48 static ReactorItem *g_hciRxReactorItem = NULL;
49 
50 static Semaphore *g_waitHdiInit;
51 static BtInitStatus g_hdiInitStatus = UNKNOWN;
52 
53 static HDILib *g_hdiLib = NULL;
54 
55 static bool g_transmissionCapture = false;
56 static void (*g_transmissionCallback)(uint8_t type, const uint8_t *data, uint16_t length) = NULL;
57 
58 static Thread *g_hciTxThread = NULL;
59 
60 // Function Declare
61 static void HciSendPacketCallback(void *param);
62 static void HciRecvPacketCallback(void *param);
63 
HciFreePacket(void * packet)64 static void HciFreePacket(void *packet)
65 {
66     HciPacket *hciPacket = packet;
67     if (hciPacket != NULL) {
68         PacketFree(hciPacket->packet);
69     }
70     MEM_MALLOC.free(packet);
71 }
72 
HciInitQueue()73 static int HciInitQueue()
74 {
75     int result = BT_SUCCESS;
76 
77     do {
78         g_hciTxQueue = QueueCreate(HCI_TX_QUEUE_SIZE);
79         if (g_hciTxQueue != NULL) {
80             Reactor *reactor = ThreadGetReactor(g_hciTxThread);
81             g_hciTxReactorItem =
82                 ReactorRegister(reactor, QueueGetDequeueFd(g_hciTxQueue), NULL, HciSendPacketCallback, NULL);
83         } else {
84             result = BT_OPERATION_FAILED;
85             break;
86         }
87         g_hciRxQueue = QueueCreate(HCI_RX_QUEUE_SIZE);
88         if (g_hciRxQueue != NULL) {
89             Reactor *reactor = ThreadGetReactor(BTM_GetProcessingThread());
90             g_hciRxReactorItem =
91                 ReactorRegister(reactor, QueueGetDequeueFd(g_hciRxQueue), NULL, HciRecvPacketCallback, NULL);
92         } else {
93             result = BT_OPERATION_FAILED;
94             break;
95         }
96     } while (0);
97 
98     return result;
99 }
100 
HciInitHal()101 NO_SANITIZE("cfi") static int HciInitHal()
102 {
103     int result = BT_SUCCESS;
104 
105     g_waitHdiInit = SemaphoreCreate(0);
106     int ret = g_hdiLib->hdiInit(&g_hdiCallacks);
107     if (ret == SUCCESS) {
108         SemaphoreWait(g_waitHdiInit);
109         if (g_hdiInitStatus != SUCCESS) {
110             LOG_ERROR("HdiInited failed: %{public}d", g_hdiInitStatus);
111             result = BT_OPERATION_FAILED;
112         }
113     } else {
114         LOG_ERROR("hdiInit failed: %{public}d", ret);
115         result = BT_OPERATION_FAILED;
116     }
117     SemaphoreDelete(g_waitHdiInit);
118     g_waitHdiInit = NULL;
119 
120     return result;
121 }
122 
HciCloseQueue()123 static void HciCloseQueue()
124 {
125     if (g_hciTxReactorItem != NULL) {
126         ReactorUnregister(g_hciTxReactorItem);
127         g_hciTxReactorItem = NULL;
128     }
129 
130     if (g_hciRxReactorItem != NULL) {
131         ReactorUnregister(g_hciRxReactorItem);
132         g_hciRxReactorItem = NULL;
133     }
134 
135     if (g_hciTxQueue != NULL) {
136         QueueDelete(g_hciTxQueue, HciFreePacket);
137         g_hciTxQueue = NULL;
138     }
139 
140     if (g_hciRxQueue != NULL) {
141         QueueDelete(g_hciRxQueue, HciFreePacket);
142         g_hciRxQueue = NULL;
143     }
144 }
145 
HCI_Initialize()146 int HCI_Initialize()
147 {
148     LOG_DEBUG("%{public}s start", __FUNCTION__);
149     int result;
150 
151     do {
152         g_hdiLib = LoadHdiLib();
153         if (g_hdiLib == NULL) {
154             result = BT_OPERATION_FAILED;
155             break;
156         }
157 
158         HciInitFailure();
159         HciInitCmd();
160         HciInitEvent();
161         HciInitAcl();
162         HciVendorInit();
163 
164         g_hciTxThread = ThreadCreate("HciTx");
165         if (g_hciTxThread == NULL) {
166             result = BT_OPERATION_FAILED;
167             break;
168         }
169 
170         result = HciInitQueue();
171         if (result != BT_SUCCESS) {
172             break;
173         }
174 
175         result = HciInitHal();
176     } while (0);
177 
178     if (result != BT_SUCCESS) {
179         if (g_hdiLib != NULL) {
180             UnloadHdiLib(g_hdiLib);
181             g_hdiLib = NULL;
182         }
183 
184         HciCloseQueue();
185 
186         if (g_hciTxThread != NULL) {
187             ThreadDelete(g_hciTxThread);
188             g_hciTxThread = NULL;
189         }
190     }
191     LOG_DEBUG("%{public}s end", __FUNCTION__);
192     return result;
193 }
194 
CleanTxPacket()195 static void CleanTxPacket()
196 {
197     if (g_hciTxQueue != NULL) {
198         HciPacket *packet = QueueTryDequeue(g_hciTxQueue);
199         while (packet != NULL) {
200             HciFreePacket(packet);
201             packet = QueueTryDequeue(g_hciTxQueue);
202         }
203     }
204 }
205 
CleanRxPacket()206 static void CleanRxPacket()
207 {
208     if (g_hciRxQueue != NULL) {
209         HciPacket *packet = QueueTryDequeue(g_hciRxQueue);
210         while (packet != NULL) {
211             HciFreePacket(packet);
212             packet = QueueTryDequeue(g_hciTxQueue);
213         }
214     }
215 }
216 
WaitRxTaskCompleteTask(void * context)217 static void WaitRxTaskCompleteTask(void *context)
218 {
219     Event *taskCompleteEvent = (Event *)context;
220     if (taskCompleteEvent != NULL) {
221         EventSet(taskCompleteEvent);
222     }
223 }
224 
WaitRxTaskComplete()225 static void WaitRxTaskComplete()
226 {
227     const int taskTimeout = 1000;
228 
229     Event *taskCompleteEvent = EventCreate(true);
230     if (taskCompleteEvent != NULL) {
231         ThreadPostTask(BTM_GetProcessingThread(), WaitRxTaskCompleteTask, taskCompleteEvent);
232         EventWait(taskCompleteEvent, taskTimeout);
233         EventDelete(taskCompleteEvent);
234     }
235 }
236 
HCI_Close()237 NO_SANITIZE("cfi") void HCI_Close()
238 {
239     LOG_DEBUG("%{public}s start", __FUNCTION__);
240 
241     CleanTxPacket();
242 
243     if (g_hciTxReactorItem != NULL) {
244         ReactorUnregister(g_hciTxReactorItem);
245         g_hciTxReactorItem = NULL;
246     }
247 
248     if (g_hciTxThread != NULL) {
249         ThreadDelete(g_hciTxThread);
250         g_hciTxThread = NULL;
251     }
252 
253     if (g_hdiLib != NULL && g_hdiLib->hdiClose != NULL) {
254         g_hdiLib->hdiClose();
255     }
256 
257     CleanRxPacket();
258 
259     if (g_hciRxReactorItem != NULL) {
260         ReactorUnregister(g_hciRxReactorItem);
261         g_hciRxReactorItem = NULL;
262     }
263 
264     WaitRxTaskComplete();
265 
266     if (g_hciTxQueue != NULL) {
267         QueueDelete(g_hciTxQueue, HciFreePacket);
268         g_hciTxQueue = NULL;
269     }
270 
271     if (g_hciRxQueue != NULL) {
272         QueueDelete(g_hciRxQueue, HciFreePacket);
273         g_hciRxQueue = NULL;
274     }
275 
276     HciCloseCmd();
277     HciCloseEvent();
278     HciCloseAcl();
279     HciCloseFailure();
280     HciVendorClose();
281 
282     if (g_hdiLib != NULL) {
283         UnloadHdiLib(g_hdiLib);
284         g_hdiLib = NULL;
285     }
286 
287     LOG_DEBUG("%{public}s end", __FUNCTION__);
288 }
289 
HciOnHDIInited(BtInitStatus status)290 static void HciOnHDIInited(BtInitStatus status)
291 {
292     g_hdiInitStatus = status;
293     SemaphorePost(g_waitHdiInit);
294 }
295 
HciOnReceivedHciPacket(BtPacketType type,const BtPacket * btPacket)296 static void HciOnReceivedHciPacket(BtPacketType type, const BtPacket *btPacket)
297 {
298     if (g_transmissionCapture && g_transmissionCallback != NULL) {
299         uint8_t transType = (type == PACKET_TYPE_EVENT) ? TRANSMISSON_TYPE_C2H_EVENT : TRANSMISSON_TYPE_C2H_DATA;
300         g_transmissionCallback(transType, btPacket->data, btPacket->size);
301     }
302 
303     HciPacket *hciPacket = MEM_MALLOC.alloc(sizeof(HciPacket));
304     if (hciPacket != NULL) {
305         switch (type) {
306             case PACKET_TYPE_ACL:
307                 hciPacket->type = C2H_ACLDATA;
308                 break;
309             case PACKET_TYPE_EVENT:
310                 hciPacket->type = C2H_EVENT;
311                 break;
312             default:
313                 break;
314         }
315 
316         hciPacket->packet = PacketMalloc(0, 0, btPacket->size);
317         PacketPayloadWrite(hciPacket->packet, btPacket->data, 0, btPacket->size);
318 
319         QueueEnqueue(g_hciRxQueue, hciPacket);
320     }
321 }
322 
HciSendPacketCallback(void * param)323 NO_SANITIZE("cfi") static void HciSendPacketCallback(void *param)
324 {
325     HciPacket *packet = QueueTryDequeue(g_hciTxQueue);
326     if (packet != NULL) {
327         BtPacket btPacket;
328         btPacket.size = PacketSize(packet->packet);
329         btPacket.data = MEM_MALLOC.alloc(btPacket.size);
330         PacketRead(packet->packet, btPacket.data, 0, btPacket.size);
331 
332         int result;
333 
334         if (g_hdiLib == NULL) {
335             LOG_ERROR("HDI is invalid.");
336             return;
337         }
338 
339         switch (packet->type) {
340             case H2C_CMD:
341                 result = g_hdiLib->hdiSendHciPacket(PACKET_TYPE_CMD, &btPacket);
342                 break;
343             case H2C_ACLDATA:
344                 result = g_hdiLib->hdiSendHciPacket(PACKET_TYPE_ACL, &btPacket);
345                 break;
346             case H2C_SCODATA:
347                 result = g_hdiLib->hdiSendHciPacket(PACKET_TYPE_SCO, &btPacket);
348                 break;
349             default:
350                 result = UNKNOWN;
351                 break;
352         }
353 
354         if (result != SUCCESS) {
355             LOG_ERROR("Send packet to HDI failed: %{public}d", result);
356         } else {
357             if (g_transmissionCapture && g_transmissionCallback != NULL) {
358                 uint8_t type = (packet->type == H2C_CMD) ? TRANSMISSON_TYPE_H2C_CMD : TRANSMISSON_TYPE_H2C_DATA;
359                 g_transmissionCallback(type, btPacket.data, btPacket.size);
360             }
361         }
362 
363         MEM_MALLOC.free(btPacket.data);
364         HciFreePacket(packet);
365     }
366 }
367 
HciRecvPacketCallback(void * param)368 static void HciRecvPacketCallback(void *param)
369 {
370     HciPacket *packet = QueueTryDequeue(g_hciRxQueue);
371     if (packet != NULL) {
372         switch (packet->type) {
373             case C2H_ACLDATA:
374                 HciOnAclData(packet->packet);
375                 break;
376             case C2H_EVENT:
377                 HciOnEvent(packet->packet);
378                 break;
379             case C2H_SCODATA:
380                 // NOT IMPLETEMENTED
381                 break;
382             default:
383                 break;
384         }
385         HciFreePacket(packet);
386     }
387 }
388 
HciPushToTxQueue(HciPacket * packet)389 void HciPushToTxQueue(HciPacket *packet)
390 {
391     QueueEnqueue(g_hciTxQueue, packet);
392 }
393 
HCI_SetTransmissionCaptureCallback(void (* onTransmission)(uint8_t type,const uint8_t * data,uint16_t length))394 int HCI_SetTransmissionCaptureCallback(void (*onTransmission)(uint8_t type, const uint8_t *data, uint16_t length))
395 {
396     g_transmissionCallback = onTransmission;
397     return BT_SUCCESS;
398 }
399 
HCI_EnableTransmissionCapture()400 int HCI_EnableTransmissionCapture()
401 {
402     g_transmissionCapture = true;
403     return BT_SUCCESS;
404 }
405 
HCI_DisableTransmissionCapture()406 int HCI_DisableTransmissionCapture()
407 {
408     g_transmissionCapture = false;
409     return BT_SUCCESS;
410 }
411 
412 static BtHciCallbacks g_hdiCallacks = {
413     .OnInited = HciOnHDIInited,
414     .OnReceivedHciPacket = HciOnReceivedHciPacket,
415 };
416