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 48static BtHciCallbacks g_hdiCallacks; 49 50static Queue *g_hciTxQueue = NULL; 51static Queue *g_hciRxQueue = NULL; 52 53static ReactorItem *g_hciTxReactorItem = NULL; 54static ReactorItem *g_hciRxReactorItem = NULL; 55 56static Semaphore *g_waitHdiInit; 57static BtInitStatus g_hdiInitStatus = UNKNOWN; 58static Alarm *g_waitHdiInitAlarm = NULL; 59 60static HDILib *g_hdiLib = NULL; 61 62static bool g_transmissionCapture = false; 63static void (*g_transmissionCallback)(uint8_t type, const uint8_t *data, uint16_t length) = NULL; 64 65static Thread *g_hciTxThread = NULL; 66 67// Function Declare 68static void HciSendPacketCallback(void *param); 69static void HciRecvPacketCallback(void *param); 70 71static 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 80static 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 92static 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 120NO_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 148static 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 171int 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 223static 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 234static 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 245static void WaitRxTaskCompleteTask(void *context) 246{ 247 Event *taskCompleteEvent = (Event *)context; 248 if (taskCompleteEvent != NULL) { 249 EventSet(taskCompleteEvent); 250 } 251} 252 253static 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 265NO_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 324static 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 335static 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 362NO_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 407static 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 428void HciPushToTxQueue(HciPacket *packet) 429{ 430 QueueEnqueue(g_hciTxQueue, packet); 431} 432 433int 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 439int HCI_EnableTransmissionCapture() 440{ 441 g_transmissionCapture = true; 442 return BT_SUCCESS; 443} 444 445int HCI_DisableTransmissionCapture() 446{ 447 g_transmissionCapture = false; 448 return BT_SUCCESS; 449} 450 451static BtHciCallbacks g_hdiCallacks = { 452 .OnInited = HciOnHDIInited, 453 .OnReceivedHciPacket = HciOnReceivedHciPacket, 454}; 455