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