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