3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2019 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * Provides an implementation of the BLEManager object for cc13xx_cc26xx
22 * platform using the Texas Instruments SDK and the OpenThread stack.
26 /* this file behaves like a config.h, comes first */
27 #include <platform/internal/CHIPDeviceLayerInternal.h>
29 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
31 #include <ble/CHIPBleServiceData.h>
32 #include <platform/internal/BLEManager.h>
38 /* Include DMM module */
39 #include "chipOBleProfile.h"
40 #include "hal_types.h"
41 #include "ti_dmm_application_policy.h"
43 #include <devinfoservice.h>
44 #include <dmm/apps/common/freertos/util.h>
45 #include <dmm/dmm_policy.h>
46 #include <dmm/dmm_priority_ble_thread.h>
47 #include <dmm/dmm_scheduler.h>
49 #include <icall_ble_api.h>
53 #include "ti_ble_config.h"
54 #include "ti_drivers_config.h"
55 #ifndef ICALL_FEATURE_SEPARATE_IMGINFO
56 #include <icall_addrs.h>
57 #endif /* ICALL_FEATURE_SEPARATE_IMGINFO */
60 // BLE Manager Debug Logs
62 #ifdef BLEMGR_DBG_LOGGING
63 extern void cc13x2_26x2Log(const char * aFormat, ...);
64 #define BLEMGR_LOG(...) cc13x2_26x2Log(__VA_ARGS__);
66 #define BLEMGR_LOG(...)
70 #ifndef USE_DEFAULT_USER_CFG
71 #include "ble_user_config.h"
72 // BLE user defined configuration. Required to be globally accesible for BLE initialization
73 icall_userCfg_t user0Cfg = BLE_USER_CFG;
74 #endif // USE_DEFAULT_USER_CFG
76 using namespace ::chip;
77 using namespace ::chip::Ble;
80 namespace DeviceLayer {
83 /* Static class member initialization */
84 BLEManagerImpl BLEManagerImpl::sInstance;
85 TaskHandle_t BLEManagerImpl::sBleTaskHndl;
86 ICall_EntityID BLEManagerImpl::sSelfEntity;
87 ICall_SyncHandle BLEManagerImpl::sSyncEvent;
88 QueueHandle_t BLEManagerImpl::sEventHandlerMsgQueueID;
89 chipOBleProfileCBs_t BLEManagerImpl::CHIPoBLEProfile_CBs = {
90 // Provisioning GATT Characteristic value change callback
91 CHIPoBLEProfile_charValueChangeCB
94 // GAP Bond Manager Callbacks
95 gapBondCBs_t BLEManagerImpl::BLEMgr_BondMgrCBs = {
96 PasscodeCb, // Passcode callback
97 PairStateCb // Pairing/Bonding state Callback
100 // ===== Members that implement the BLEManager internal interface.
101 CHIP_ERROR BLEManagerImpl::_Init(void)
103 CHIP_ERROR err = CHIP_NO_ERROR;
105 BLEMGR_LOG("BLEMGR: BLE Initialization Start");
106 // Initialize the CHIP BleLayer.
107 err = BleLayer::Init(this, this, &SystemLayer);
108 if (err != CHIP_NO_ERROR)
113 /* Register BLE Stack assert handler */
114 RegisterAssertCback(AssertHandler);
116 mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
117 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
119 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
120 OnChipBleConnectReceived = HandleIncomingBleConnection;
122 err = CreateEventHandler();
126 BLEManager::CHIPoBLEServiceMode BLEManagerImpl::_GetCHIPoBLEServiceMode(void)
131 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(BLEManager::CHIPoBLEServiceMode val)
135 /* Trigger state update */
136 return DriveBLEState();
139 bool BLEManagerImpl::_IsAdvertisingEnabled(void)
141 return mFlags.Has(Flags::kAdvertisingEnabled);
144 /* Post event to app processing loop to begin CHIP advertising */
145 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
147 mFlags.Set(Flags::kAdvertisingEnabled, val);
149 /* Send event to process state change request */
150 return DriveBLEState();
153 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
155 CHIP_ERROR ret = CHIP_NO_ERROR;
159 case BLEAdvertisingMode::kFastAdvertising:
160 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
162 case BLEAdvertisingMode::kSlowAdvertising:
163 mFlags.Set(Flags::kFastAdvertisingEnabled, false);
166 return CHIP_ERROR_INVALID_ARGUMENT;
168 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
169 ret = DriveBLEState();
173 bool BLEManagerImpl::_IsAdvertising(void)
175 return mFlags.Has(Flags::kAdvertising);
178 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
180 CHIP_ERROR ret = CHIP_NO_ERROR;
182 if (bufSize <= GAP_DEVICE_NAME_LEN)
184 strncpy(buf, mDeviceName, bufSize);
188 ret = CHIP_ERROR_BUFFER_TOO_SMALL;
194 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * deviceName)
196 CHIP_ERROR ret = CHIP_NO_ERROR;
198 if (strlen(deviceName) <= GAP_DEVICE_NAME_LEN)
200 strncpy(mDeviceName, deviceName, strlen(deviceName));
202 mFlags.Set(Flags::kBLEStackGATTNameUpdate);
204 ret = DriveBLEState();
208 ret = CHIP_ERROR_BUFFER_TOO_SMALL;
214 uint16_t BLEManagerImpl::_NumConnections(void)
216 uint8_t i, numConns = 0;
218 // Try to find an available entry
219 for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
221 if (connList[i].connHandle != LL_CONNHANDLE_INVALID)
230 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
234 case DeviceEventType::kCHIPoBLESubscribe: {
235 ChipDeviceEvent connEstEvent;
237 BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLESubscribe");
238 HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
240 connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
242 PlatformMgr().PostEvent(&connEstEvent);
246 case DeviceEventType::kCHIPoBLEUnsubscribe: {
247 BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEUnsubscribe");
248 HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
252 case DeviceEventType::kCHIPoBLEWriteReceived: {
253 BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEWriteReceived");
254 HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
255 PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
259 case DeviceEventType::kCHIPoBLEIndicateConfirm:
260 HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
263 case DeviceEventType::kCHIPoBLEConnectionError: {
264 BLEMGR_LOG("BLEMGR: OnPlatformEvent, kCHIPoBLEConnectionError");
265 HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
274 // ===== Members that implement virtual methods on BlePlatformDelegate.
275 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
277 void * pMsg = (void *) ICall_malloc(sizeof(void *));
278 pMsg = (void *) conId;
280 EnqueueEvtHdrMsg(BLEManagerIMPL_CHIPOBLE_CLOSE_CONN_EVT, (void *) pMsg);
282 return CHIP_NO_ERROR;
285 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
290 index = GetBLEConnIndex(*((uint32_t *) conId));
292 if (index != MAX_NUM_BLE_CONNS)
294 mtu = sInstance.connList[index].mtu;
295 /* Prior to MTU update event, MTU is determined by the below formula */
298 mtu = MAX_PDU_SIZE - 4;
305 // ===== Members that implement virtual methods on BleApplicationDelegate.
307 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
312 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
313 PacketBufferHandle data)
315 BLEMGR_LOG("BLEMGR: BLE SendIndication ");
317 // Allocate buffers to send to BLE app task
318 uint8_t dataLen = static_cast<uint8_t>(data->DataLength());
319 CHIPoBLEIndEvt_t * pMsg;
322 pMsg = (CHIPoBLEIndEvt_t *) ICall_malloc(sizeof(CHIPoBLEIndEvt_t));
328 pBuf = (uint8_t *) ICall_malloc(dataLen);
331 ICall_free((void *) pMsg);
335 memset(pBuf, 0x00, dataLen);
336 memcpy(pBuf, data->Start(), dataLen);
341 EnqueueEvtHdrMsg(BLEManagerIMPL_CHIPOBLE_TX_IND_EVT, (void *) pMsg);
343 BLEMGR_LOG("BLEMGR: BLE SendIndication RETURN, Length: %d ", dataLen);
347 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
348 const Ble::ChipBleUUID * charId)
350 /* Unsupported on TI peripheral device implementation */
354 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
355 const Ble::ChipBleUUID * charId)
357 /* Unsupported on TI peripheral device implementation */
361 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
362 PacketBufferHandle pBuf)
364 /* Unsupported on TI peripheral device implementation */
368 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
369 PacketBufferHandle pBuf)
371 /* Unsupported on TI peripheral device implementation */
375 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
376 const ChipBleUUID * svcId, const ChipBleUUID * charId)
378 /* Unsupported on TI peripheral device implementation */
382 void BLEManagerImpl::HandleIncomingBleConnection(BLEEndPoint * bleEP)
384 BLEMGR_LOG("BLEMGR: HandleIncomingBleConnection");
387 // ===== Helper Members that implement the Low level BLE Stack behavior.
389 /*********************************************************************
392 * @brief Initialize CHIPoBLE Advertisement.
394 * @param pMsg - message to process
396 void BLEManagerImpl::AdvInit(void)
398 bStatus_t status = FAILURE;
399 uint16_t deviceDiscriminator;
400 uint8_t localDeviceNameLen;
401 uint8_t scanIndex = 0;
402 uint8_t advIndex = 0;
403 uint8_t scanResLength;
405 uint8_t * advDatachipOBle;
406 uint8_t * scanResDatachipOBle;
408 BLEMGR_LOG("BLEMGR: AdvInit");
410 ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
411 ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
413 // Verify device name was not already set
414 if (!sInstance.mFlags.Has(Flags::kBLEStackGATTNameSet))
416 /* Default device name is CHIP-<DISCRIMINATOR> */
417 deviceDiscriminator = mDeviceIdInfo.GetDeviceDiscriminator();
419 localDeviceNameLen = strlen(CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX) + sizeof(deviceDiscriminator);
421 memset(sInstance.mDeviceName, 0, GAP_DEVICE_NAME_LEN);
422 snprintf(sInstance.mDeviceName, GAP_DEVICE_NAME_LEN, "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX,
423 deviceDiscriminator);
425 // Set the Device Name characteristic in the GAP GATT Service
426 // For more information, see the section in the User's Guide:
427 // http://software-dl.ti.com/lprf/ble5stack-latest/
428 GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, sInstance.mDeviceName);
430 BLEMGR_LOG("BLEMGR: AdvInit New device name set: %s", sInstance.mDeviceName);
434 localDeviceNameLen = strlen(sInstance.mDeviceName);
437 scanResLength = localDeviceNameLen + CHIPOBLE_SCANRES_SIZE_NO_NAME;
439 scanResDatachipOBle = (uint8_t *) ICall_malloc(scanResLength);
441 scanResDatachipOBle[scanIndex++] = localDeviceNameLen + 1;
442 scanResDatachipOBle[scanIndex++] = GAP_ADTYPE_LOCAL_NAME_COMPLETE;
443 memcpy(&scanResDatachipOBle[scanIndex], sInstance.mDeviceName, localDeviceNameLen);
444 scanIndex += localDeviceNameLen;
445 scanResDatachipOBle[scanIndex++] = 0x03;
446 scanResDatachipOBle[scanIndex++] = GAP_ADTYPE_16BIT_COMPLETE;
447 scanResDatachipOBle[scanIndex++] = static_cast<uint8_t>(LO_UINT16(CHIPOBLE_SERV_UUID));
448 scanResDatachipOBle[scanIndex++] = static_cast<uint8_t>(HI_UINT16(CHIPOBLE_SERV_UUID));
450 for (uint8_t temp = 0; temp < scanIndex; temp++)
452 BLEMGR_LOG("BLEMGR: AdvInit Scan Response Data: %x", scanResDatachipOBle[temp]);
455 advLength = sizeof(static_cast<uint16_t>(CHIPOBLE_SERV_UUID)) + static_cast<uint8_t>(sizeof(mDeviceIdInfo)) + 1;
456 advDatachipOBle = (uint8_t *) ICall_malloc(CHIPOBLE_ADV_SIZE_NO_DEVICE_ID_INFO + advLength);
458 BLEMGR_LOG("BLEMGR: AdvInit: MDeviceIDInfo Size: %d", sizeof(mDeviceIdInfo));
459 BLEMGR_LOG("BLEMGR: AdvInit: advlength: %d", advLength);
460 BLEMGR_LOG("BLEMGR: AdvInit:Desc : %d", mDeviceIdInfo.GetDeviceDiscriminator());
462 advDatachipOBle[advIndex++] = 0x02;
463 advDatachipOBle[advIndex++] = GAP_ADTYPE_FLAGS;
464 advDatachipOBle[advIndex++] = GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED | GAP_ADTYPE_FLAGS_GENERAL;
465 advDatachipOBle[advIndex++] = advLength;
466 advDatachipOBle[advIndex++] = GAP_ADTYPE_SERVICE_DATA;
467 advDatachipOBle[advIndex++] = static_cast<uint8_t>(LO_UINT16(CHIPOBLE_SERV_UUID));
468 advDatachipOBle[advIndex++] = static_cast<uint8_t>(HI_UINT16(CHIPOBLE_SERV_UUID));
469 memcpy(&advDatachipOBle[advIndex], (void *) &mDeviceIdInfo, static_cast<uint8_t>(sizeof(mDeviceIdInfo)));
471 // Setup and start Advertising
472 // For more information, see the GAP section in the User's Guide:
473 // http://software-dl.ti.com/lprf/ble5stack-latest/
475 // Create Advertisement set #1 and assign handle
476 status = (bStatus_t) GapAdv_create(&advCallback, &advParams1, &sInstance.advHandleLegacy);
477 assert(status == SUCCESS);
479 // Load advertising data for set #1 that is statically allocated by the app
480 status = (bStatus_t) GapAdv_loadByHandle(sInstance.advHandleLegacy, GAP_ADV_DATA_TYPE_ADV,
481 CHIPOBLE_ADV_SIZE_NO_DEVICE_ID_INFO + advLength, advDatachipOBle);
483 // Load scan response data for set #1 that is statically allocated by the app
485 (bStatus_t) GapAdv_loadByHandle(sInstance.advHandleLegacy, GAP_ADV_DATA_TYPE_SCAN_RSP, scanResLength, scanResDatachipOBle);
486 assert(status == SUCCESS);
488 // Set event mask for set #1
489 status = (bStatus_t) GapAdv_setEventMask(sInstance.advHandleLegacy,
490 GAP_ADV_EVT_MASK_START_AFTER_ENABLE | GAP_ADV_EVT_MASK_END_AFTER_DISABLE |
491 GAP_ADV_EVT_MASK_SET_TERMINATED);
493 Util_constructClock(&sInstance.clkAdvTimeout, AdvTimeoutHandler, ADV_TIMEOUT, 0, false, (uintptr_t) NULL);
496 /*********************************************************************
497 * @fn EventHandler_init
499 * @brief Called during initialization and contains application
500 * specific initialization (ie. hardware initialization/setup,
501 * table initialization, power up notification, etc), and
502 * profile initialization/setup.
504 void BLEManagerImpl::EventHandler_init(void)
506 BLEMGR_LOG("BLEMGR: EventHandler_init");
508 /* Update User Configuration of the stack */
509 user0Cfg.appServiceInfo->timerTickPeriod = ICall_getTickPeriod();
510 user0Cfg.appServiceInfo->timerMaxMillisecond = ICall_getMaxMSecs();
512 /* Initialize ICall module */
515 /* Start tasks of external images */
516 ICall_createRemoteTasks();
517 BLEManagerImpl::sBleTaskHndl = (TaskHandle_t)(*((TaskHandle_t *) ICall_getRemoteTaskHandle(0)));
518 DMMSch_registerClient((TaskHandle_t) BLEManagerImpl::sBleTaskHndl, DMMPolicy_StackRole_BlePeripheral);
519 /* set the stacks in default states */
520 DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_IDLE);
522 vTaskPrioritySet(xTaskGetCurrentTaskHandle(), 3);
524 // ******************************************************************
525 // N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
526 // ******************************************************************
527 // Register the current thread as an ICall dispatcher application
528 // so that the application can send and receive messages.
529 ICall_registerApp(&BLEManagerImpl::sSelfEntity, &BLEManagerImpl::sSyncEvent);
532 RCOSC_enableCalibration();
535 // Create an RTOS queue for message from profile to be sent to app.
536 Util_constructQueue(&BLEManagerImpl::sEventHandlerMsgQueueID);
540 uint16_t paramUpdateDecision = DEFAULT_PARAM_UPDATE_REQ_DECISION;
542 // Pass all parameter update requests to the app for it to decide
543 GAP_SetParamValue(GAP_PARAM_LINK_UPDATE_DECISION, paramUpdateDecision);
546 // Setup the GAP Bond Manager. For more information see the GAP Bond Manager
547 // section in the User's Guide:
548 // http://software-dl.ti.com/lprf/ble5stack-latest/
549 setBondManagerParameters();
551 // Initialize GATT attributes
552 GGS_AddService(GATT_ALL_SERVICES); // GAP GATT Service
553 GATTServApp_AddService(GATT_ALL_SERVICES); // GATT Service
554 DevInfo_AddService(); // Device Information Service
556 CHIPoBLEProfile_AddService(GATT_ALL_SERVICES);
558 // Start Bond Manager and register callback
559 VOID GAPBondMgr_Register(BLEMgr_BondMgrCBs);
561 // Register with GAP for HCI/Host messages. This is needed to receive HCI
562 // events. For more information, see the HCI section in the User's Guide:
563 // http://software-dl.ti.com/lprf/ble5stack-latest/
564 GAP_RegisterForMsgs(BLEManagerImpl::sSelfEntity);
566 // Register for GATT local events and ATT Responses pending for transmission
567 GATT_RegisterForMsgs(BLEManagerImpl::sSelfEntity);
569 CHIPoBLEProfile_RegisterAppCBs(&CHIPoBLEProfile_CBs);
570 // Set default values for Data Length Extension
571 // Extended Data Length Feature is already enabled by default
573 // This API is documented in hci.h
574 // See the LE Data Length Extension section in the BLE5-Stack User's Guide for information on using this command:
575 // http://software-dl.ti.com/lprf/ble5stack-latest/
576 HCI_LE_WriteSuggestedDefaultDataLenCmd(BLEMANAGER_SUGGESTED_PDU_SIZE, BLEMANAGER_SUGGESTED_TX_TIME);
579 // Initialize GATT Client
582 // Initialize Connection List
583 ClearBLEConnListEntry(LL_CONNHANDLE_ALL);
585 // Initialize GAP layer for Peripheral role and register to receive GAP events
586 GAP_DeviceInit(GAP_PROFILE_PERIPHERAL, BLEManagerImpl::sSelfEntity, sInstance.addrMode, &pRandomAddress);
588 // Initialize array to store connection handle and RSSI values
592 /*********************************************************************
593 * @fn InitPHYRSSIArray
595 * @brief Initializes the array of structure/s to store data related
596 * RSSI based auto PHy change
598 * @param connHandle - the connection handle
600 * @param addr - pointer to device address
602 * @return index of connection handle
604 void BLEManagerImpl::InitPHYRSSIArray(void)
606 BLEMGR_LOG("BLEMGR: InitPHYRSSIArray");
608 // Initialize array to store connection handle and RSSI values
609 memset(sInstance.connList, 0, sizeof(sInstance.connList));
611 for (uint8_t index = 0; index < MAX_NUM_BLE_CONNS; index++)
613 sInstance.connList[index].connHandle = INVALID_HANDLE;
617 /*********************************************************************
618 * @fn CreateEventHandler
620 * @brief Create FreeRTOS Task for BLE Event handling
623 CHIP_ERROR BLEManagerImpl::CreateEventHandler(void)
625 BLEMGR_LOG("BLEMGR: CreateEventHandler");
627 BaseType_t xReturned;
629 /* Create the task, storing the handle. */
630 xReturned = xTaskCreate(EventHandler, /* Function that implements the task. */
631 "ble_hndlr", /* Text name for the task. */
632 4096 / sizeof(uint32_t), /* Stack size in words, not bytes. */
633 this, /* Parameter passed into the task. */
634 ICALL_TASK_PRIORITIES, /* Keep priority the same as ICALL until init is complete */
635 NULL); /* Used to pass out the created task's handle. */
637 if (xReturned == errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY)
639 return CHIP_ERROR_NO_MEMORY;
643 return CHIP_NO_ERROR;
647 /*********************************************************************
648 * @fn RemoteDisplay_processStackMsg
650 * @brief Process an incoming stack message.
652 * @param pMsg - message to process
654 * @return TRUE if safe to deallocate incoming message, FALSE otherwise.
656 uint8_t BLEManagerImpl::ProcessStackEvent(ICall_Hdr * pMsg)
658 BLEMGR_LOG("BLEMGR: BLE Process Stack Event");
660 // Always dealloc pMsg unless set otherwise
661 uint8_t safeToDealloc = TRUE;
666 ProcessGapMessage((gapEventHdr_t *) pMsg);
670 // Process GATT message
671 safeToDealloc = ProcessGATTMsg((gattMsgEvent_t *) pMsg);
673 case HCI_GAP_EVENT_EVENT: {
674 // Process HCI message
675 switch (pMsg->status)
677 case HCI_COMMAND_COMPLETE_EVENT_CODE:
678 // Process HCI Command Complete Events here
680 // RemoteDisplay_processCmdCompleteEvt((hciEvt_CmdComplete_t *) pMsg);
683 case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
686 // HCI Commands Events
687 case HCI_COMMAND_STATUS_EVENT_CODE: {
688 hciEvt_CommandStatus_t * pMyMsg = (hciEvt_CommandStatus_t *) pMsg;
689 switch (pMyMsg->cmdOpcode)
691 case HCI_LE_SET_PHY: {
692 if (pMyMsg->cmdStatus == HCI_ERROR_CODE_UNSUPPORTED_REMOTE_FEATURE)
694 /* PHY Change failure, peer does not support this */
704 case HCI_LE_EVENT_CODE: {
705 hciEvt_BLEPhyUpdateComplete_t * pPUC = (hciEvt_BLEPhyUpdateComplete_t *) pMsg;
707 // A Phy Update Has Completed or Failed
708 if (pPUC->BLEEventCode == HCI_BLE_PHY_UPDATE_COMPLETE_EVENT)
710 if (pPUC->status != SUCCESS)
712 /* PHY Change failure */
716 /* PHY Update successfull */
733 return safeToDealloc;
736 /*********************************************************************
737 * @fn ProcessEvtHdrMsg
739 * @brief Process an incoming callback from a profile.
741 * @param pMsg - message to process
745 void BLEManagerImpl::ProcessEvtHdrMsg(QueuedEvt_t * pMsg)
749 BLEMGR_LOG("BLEMGR: ProcessEvtHdrMsg");
753 /* External CHIPoBLE Event trigger */
754 case BLEManagerIMPL_STATE_UPDATE_EVT: {
757 /* Verify BLE service mode is enabled */
758 if (sInstance.mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled)
760 /* Advertising flag set, either advertising or fast adv is enabled: Do nothing */
761 /* Advertising flag not set, neither advertising nor fast adv is enabled: do nothing */
762 /* Advertising flag not set, either advertising or fast adv is enabled: Turn on */
763 if (!sInstance.mFlags.Has(Flags::kAdvertising))
765 BLEMGR_LOG("BLEMGR: BLE Process Application Message: Not advertising");
767 if (sInstance.mFlags.Has(Flags::kAdvertisingEnabled))
770 // Send notification to thread manager that CHIPoBLE advertising is starting
771 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
772 ThreadStackMgr().OnCHIPoBLEAdvertisingStart();
773 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
775 // Enable legacy advertising for set #1
776 status = (bStatus_t) GapAdv_enable(sInstance.advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
778 assert(status == SUCCESS);
780 sInstance.mFlags.Set(Flags::kAdvertising);
782 if (sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled))
784 BLEMGR_LOG("BLEMGR: BLE Process Application Message: Fast Advertising Enabled");
788 BLEMGR_LOG("BLEMGR: BLE Process Application Message: Slow Advertising Enabled");
790 // Start advertisement timer
791 Util_startClock(&sInstance.clkAdvTimeout);
795 /* Advertising flag set, neither advertising nor fast adv is enabled: Turn off*/
796 else if (!sInstance.mFlags.Has(Flags::kAdvertisingEnabled) && !sInstance.mFlags.Has(Flags::kFastAdvertisingEnabled))
798 BLEMGR_LOG("BLEMGR: BLE Process Application Message: Advertising disables");
801 GapAdv_disable(sInstance.advHandleLegacy);
802 sInstance.mFlags.Clear(Flags::kAdvertising);
803 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
805 Util_stopClock(&sInstance.clkAdvTimeout);
807 /* Other case is that advertising is already working, but should be restarted, as its settings changed */
808 else if (sInstance.mFlags.Has(Flags::kAdvertisingRefreshNeeded))
810 sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
811 GapAdv_disable(sInstance.advHandleLegacy);
813 // Enable legacy advertising for set #1
814 status = (bStatus_t) GapAdv_enable(sInstance.advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX, 0);
815 assert(status == SUCCESS);
816 sInstance.mFlags.Set(Flags::kAdvertising);
820 if (sInstance.mFlags.Has(Flags::kBLEStackGATTNameUpdate))
822 sInstance.mFlags.Clear(Flags::kBLEStackGATTNameUpdate);
823 // Indicate that Device name has been set externally
824 mFlags.Set(Flags::kBLEStackGATTNameSet);
826 // Set the Device Name characteristic in the GAP GATT Service
827 GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, sInstance.mDeviceName);
832 case BLEManagerIMPL_CHIPOBLE_CLOSE_CONN_EVT: {
833 uint16_t connHandle = *((uint16_t *) (pMsg->pData));
835 // Close active connection
836 GAP_TerminateLinkReq(connHandle, HCI_DISCONNECT_REMOTE_USER_TERM);
840 case BLEManagerIMPL_CHIPOBLE_TX_IND_EVT: {
841 uint8_t dataLen = ((CHIPoBLEIndEvt_t *) (pMsg->pData))->len;
843 CHIPoBLEProfile_SetParameter(CHIPOBLEPROFILE_TX_CHAR, dataLen, (void *) (((CHIPoBLEIndEvt_t *) (pMsg->pData))->pData),
844 BLEManagerImpl::sSelfEntity);
846 BLEMGR_LOG("BLEMGR: BLE Process Application Message: BLEManagerIMPL_CHIPOBLE_TX_IND_EVT: Length: %d", dataLen);
848 ICall_free((void *) (((CHIPoBLEIndEvt_t *) (pMsg->pData))->pData));
854 case CHIPOBLE_CHAR_CHANGE_EVT: {
855 uint16_t writeLen = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->len;
856 uint8_t paramId = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->paramId;
857 uint16_t connHandleId = ((CHIPoBLEProfChgEvt_t *) (pMsg->pData))->connHandle;
859 ChipDeviceEvent event;
862 ConnRec_t * activeConnObj = NULL;
864 // Find active connection
865 for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
867 if (sInstance.connList[i].connHandle == connHandleId)
869 activeConnObj = &sInstance.connList[i];
873 connHandle = (void *) &activeConnObj->connHandle;
875 if (paramId == CHIPOBLEPROFILE_RX_CHAR)
877 BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, CHIPOBLEPROFILE_RX_CHAR");
878 // Pull written data from CHIPOBLE Profile based on extern server write
879 uint8_t * rxBuf = (uint8_t *) ICall_malloc(writeLen);
887 memset(rxBuf, 0x00, writeLen);
889 BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, length: %d", writeLen);
890 CHIPoBLEProfile_GetParameter(CHIPOBLEPROFILE_RX_CHAR, rxBuf, writeLen);
892 System::PacketBufferHandle packetBuf = System::PacketBufferHandle::NewWithData(rxBuf, writeLen, 0, 0);
896 if (packetBuf.IsNull())
902 // Arrange to post a CHIPoBLERXWriteEvent event to the CHIP queue.
903 event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
904 event.CHIPoBLEWriteReceived.ConId = (void *) connHandle;
905 event.CHIPoBLEWriteReceived.Data = std::move(packetBuf).UnsafeRelease();
907 else if (paramId == CHIPOBLEPROFILE_CCCWrite)
909 BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, CHIPOBLEPROFILE_CCCWrite");
911 // TODO: Add check to see if subscribing OR unsubscribing from char indications
914 CHIPoBLEProfile_GetParameter(CHIPOBLEPROFILE_CCCWrite, &cccValue, 1);
916 // Check whether it is a sub/unsub event. 0x1 = Notofications enabled, 0x2 = Indications enabled
919 // Post event to CHIP
920 BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, Subscrbe");
921 event.Type = DeviceEventType::kCHIPoBLESubscribe;
925 BLEMGR_LOG("BLEMGR: BLE Process Application Message: CHIPOBLE_CHAR_CHANGE_EVT, unsubscrbe");
926 event.Type = DeviceEventType::kCHIPoBLEUnsubscribe;
929 // Post event to CHIP
930 event.CHIPoBLESubscribe.ConId = (void *) connHandle;
932 PlatformMgr().PostEvent(&event);
937 ProcessAdvEvent((GapAdvEventData_t *) (pMsg->pData));
940 case PAIR_STATE_EVT: {
941 BLEMGR_LOG("BLEMGR: PAIR_STATE_EVT");
943 // Send passcode response
944 GAPBondMgr_PasscodeRsp(((PasscodeData_t *) (pMsg->pData))->connHandle, SUCCESS, B_APP_DEFAULT_PASSCODE);
949 BLEMGR_LOG("BLEMGR: PASSCODE_EVT");
957 case SEND_PARAM_UPDATE_EVT: {
958 // Extract connection handle from data
959 uint16_t connHandle = *(uint16_t *) (((ClockEventData_t *) pMsg->pData)->data);
961 if (CHIP_NO_ERROR != ProcessParamUpdate(connHandle))
967 // This data is not dynamically allocated
970 /* If we are sending a param update request then the service discovery
971 * should have ended. Changed state to connected */
972 DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_CONNECTED);
985 // Free message data if it exists and we are to dealloc
986 if ((dealloc == TRUE) && (pMsg->pData != NULL))
988 ICall_free(pMsg->pData);
992 /*********************************************************************
993 * @fn ProcessGapMessage
995 * @brief Process an incoming GAP event.
997 * @param pMsg - message to process
999 void BLEManagerImpl::ProcessGapMessage(gapEventHdr_t * pMsg)
1001 BLEMGR_LOG("BLEMGR: ProcessGapMessage");
1003 switch (pMsg->opcode)
1005 case GAP_DEVICE_INIT_DONE_EVENT: {
1006 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_DEVICE_INIT_DONE_EVENT");
1008 gapDeviceInitDoneEvent_t * pPkt = (gapDeviceInitDoneEvent_t *) pMsg;
1010 if (pPkt->hdr.status == SUCCESS)
1012 // Store the system ID
1013 uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
1015 // use 6 bytes of device address for 8 bytes of system ID value
1016 systemId[0] = pPkt->devAddr[0];
1017 systemId[1] = pPkt->devAddr[1];
1018 systemId[2] = pPkt->devAddr[2];
1020 // set middle bytes to zero
1024 // shift three bytes up
1025 systemId[7] = pPkt->devAddr[5];
1026 systemId[6] = pPkt->devAddr[4];
1027 systemId[5] = pPkt->devAddr[3];
1029 // Set Device Info Service Parameter
1030 DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
1034 sInstance.mFlags.Set(Flags::kBLEStackInitialized);
1036 /* Trigger post-initialization state update */
1039 if (sInstance.addrMode > ADDRMODE_RANDOM)
1042 // Create one-shot clock for RPA check event.
1043 Util_constructClock(&sInstance.clkRpaRead, ClockHandler, READ_RPA_EVT_PERIOD, 0, true,
1044 (uintptr_t) &sInstance.argRpaRead);
1050 case GAP_LINK_ESTABLISHED_EVENT: {
1051 gapEstLinkReqEvent_t * pPkt = (gapEstLinkReqEvent_t *) pMsg;
1052 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_ESTABLISHED_EVENT");
1054 // Display the amount of current connections
1055 uint8_t numActive = (uint8_t) linkDB_NumActive("");
1057 if (pPkt->hdr.status == SUCCESS)
1059 // Add connection to list and start RSSI
1060 AddBLEConn(pPkt->connectionHandle);
1063 DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_HIGH_BANDWIDTH);
1065 if (numActive < MAX_NUM_BLE_CONNS)
1067 // Start advertising since there is room for more connections. Advertisements stop automatically following connection.
1068 sInstance.mFlags.Clear(Flags::kAdvertising);
1072 // Stop advertising since there is no room for more connections
1073 BLEMGR_LOG("BLEMGR: BLE event GAP_LINK_ESTABLISHED_EVENT: MAX connections");
1074 sInstance.mFlags.Clear(Flags::kAdvertisingEnabled).Clear(Flags::kAdvertising);
1075 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
1078 /* Stop advertisement timeout timer */
1079 Util_stopClock(&sInstance.clkAdvTimeout);
1086 case GAP_LINK_TERMINATED_EVENT: {
1087 gapTerminateLinkEvent_t * pPkt = (gapTerminateLinkEvent_t *) pMsg;
1088 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_TERMINATED_EVENT, reason: %d", pPkt->reason);
1090 // Remove the connection from the list and disable RSSI if needed
1091 RemoveBLEConn(pPkt->connectionHandle);
1093 ChipDeviceEvent event;
1094 event.Type = DeviceEventType::kCHIPoBLEConnectionError;
1095 event.CHIPoBLEConnectionError.ConId = (void *) &pPkt->connectionHandle;
1096 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
1097 PlatformMgr().PostEvent(&event);
1104 case GAP_UPDATE_LINK_PARAM_REQ_EVENT: {
1105 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT");
1107 gapUpdateLinkParamReqReply_t rsp;
1109 gapUpdateLinkParamReqEvent_t * pReq = (gapUpdateLinkParamReqEvent_t *) pMsg;
1111 rsp.connectionHandle = pReq->req.connectionHandle;
1112 rsp.signalIdentifier = pReq->req.signalIdentifier;
1114 // Only accept connection intervals with slave latency of 0
1115 // This is just an example of how the application can send a response
1116 if (pReq->req.connLatency == 0)
1118 rsp.intervalMin = pReq->req.intervalMin;
1119 rsp.intervalMax = pReq->req.intervalMax;
1120 rsp.connLatency = pReq->req.connLatency;
1121 rsp.connTimeout = pReq->req.connTimeout;
1122 rsp.accepted = TRUE;
1123 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT Accecpted");
1127 rsp.accepted = FALSE;
1128 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_UPDATE_LINK_PARAM_REQ_EVENT Rejected");
1132 VOID GAP_UpdateLinkParamReqReply(&rsp);
1137 case GAP_LINK_PARAM_UPDATE_EVENT: {
1138 BLEMGR_LOG("BLEMGR: ProcessGapMessage: GAP_LINK_PARAM_UPDATE_EVENT");
1140 gapLinkUpdateEvent_t * pPkt = (gapLinkUpdateEvent_t *) pMsg;
1142 // Get the address from the connection handle
1143 linkDBInfo_t linkInfo;
1144 linkDB_GetInfo(pPkt->connectionHandle, &linkInfo);
1146 // Check if there are any queued parameter updates
1147 ConnHandleEntry_t * connHandleEntry = (ConnHandleEntry_t *) List_get(&sInstance.paramUpdateList);
1148 if (connHandleEntry != NULL)
1150 // Attempt to send queued update now
1151 ProcessParamUpdate(connHandleEntry->connHandle);
1153 // Free list element
1154 ICall_free(connHandleEntry);
1165 /*********************************************************************
1166 * @fn ProcessGATTMsg
1168 * @brief Process GATT messages and events.
1170 * @return TRUE if safe to deallocate incoming message, FALSE otherwise.
1172 uint8_t BLEManagerImpl::ProcessGATTMsg(gattMsgEvent_t * pMsg)
1175 BLEMGR_LOG("BLEMGR: ProcessGATTMsg");
1177 if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
1179 // ATT request-response or indication-confirmation flow control is
1180 // violated. All subsequent ATT requests or indications will be dropped.
1181 // The app is informed in case it wants to drop the connection.
1183 else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
1185 index = GetBLEConnIndex(pMsg->connHandle);
1187 sInstance.connList[index].mtu = pMsg->msg.mtuEvt.MTU;
1188 BLEMGR_LOG("BLEMGR: ProcessGATTMsg, ATT_MTU_UPDATED_EVENT: %d", pMsg->msg.mtuEvt.MTU);
1190 else if (pMsg->method == ATT_HANDLE_VALUE_CFM)
1193 ChipDeviceEvent event;
1195 ConnRec_t * activeConnObj = NULL;
1197 activeConnObj = &sInstance.connList[0];
1198 connHandle = (void *) &activeConnObj->connHandle;
1200 event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm;
1201 event.CHIPoBLEIndicateConfirm.ConId = connHandle;
1202 PlatformMgr().PostEvent(&event);
1204 BLEMGR_LOG("BLEMGR: ProcessGATTMsg, ATT_HANDLE_VALUE_CFM:");
1206 // Free message payload. Needed only for ATT Protocol messages
1207 GATT_bm_free(&pMsg->msg, pMsg->method);
1209 // It's safe to free the incoming message
1213 /*********************************************************************
1214 * @fn ProcessAdvEvent
1216 * @brief Process advertising event in app context
1220 void BLEManagerImpl::ProcessAdvEvent(GapAdvEventData_t * pEventData)
1222 BLEMGR_LOG("BLEMGR: ProcessAdvEvent");
1224 switch (pEventData->event)
1226 case GAP_EVT_ADV_START_AFTER_ENABLE: {
1227 BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_START_AFTER_ENABLE");
1229 if (linkDB_NumActive("") == 0)
1231 DMMPolicy_updateStackState(DMMPolicy_StackRole_BlePeripheral, DMMPOLICY_BLE_ADV);
1236 case GAP_EVT_ADV_END_AFTER_DISABLE: {
1237 BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_END_AFTER_DISABLE");
1241 case GAP_EVT_ADV_START:
1244 case GAP_EVT_ADV_END:
1247 // BLE Stack has ended advertising due to connection
1248 case GAP_EVT_ADV_SET_TERMINATED: {
1249 BLEMGR_LOG("BLEMGR: ProcessAdvEvent: GAP_EVT_ADV_SET_TERMINATED");
1253 case GAP_EVT_SCAN_REQ_RECEIVED:
1256 case GAP_EVT_INSUFFICIENT_MEMORY:
1263 // All events have associated memory to free except the insufficient memory
1265 if (pEventData->event != GAP_EVT_INSUFFICIENT_MEMORY)
1267 ICall_free(pEventData->pBuf);
1271 /*********************************************************************
1272 * @fn ProcessParamUpdate
1274 * @brief Process a parameters update request
1278 CHIP_ERROR BLEManagerImpl::ProcessParamUpdate(uint16_t connHandle)
1280 gapUpdateLinkParamReq_t req;
1282 BLEMGR_LOG("BLEMGR: ProcessParamUpdate");
1284 req.connectionHandle = connHandle;
1285 req.connLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
1286 req.connTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
1287 req.intervalMin = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
1288 req.intervalMax = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
1290 connIndex = GetBLEConnIndex(connHandle);
1291 if (!(connIndex < MAX_NUM_BLE_CONNS))
1293 return CHIP_ERROR_TOO_MANY_CONNECTIONS;
1296 // Deconstruct the clock object
1297 ClockP_destruct(sInstance.connList[connIndex].pUpdateClock);
1298 // Free clock struct
1299 if (sInstance.connList[connIndex].pUpdateClock != NULL)
1301 ICall_free(sInstance.connList[connIndex].pUpdateClock);
1302 sInstance.connList[connIndex].pUpdateClock = NULL;
1304 // Free ParamUpdateEventData
1305 if (sInstance.connList[connIndex].pParamUpdateEventData != NULL)
1307 ICall_free(sInstance.connList[connIndex].pParamUpdateEventData);
1310 BLEMGR_LOG("BLEMGR: ProcessParamUpdate Send Link Param Req");
1311 // Send parameter update
1312 bStatus_t status = GAP_UpdateLinkParamReq(&req);
1314 // If there is an ongoing update, queue this for when the udpate completes
1315 if (status == bleAlreadyInRequestedMode)
1318 BLEMGR_LOG("BLEMGR: ProcessParamUpdate pending");
1319 ConnHandleEntry_t * connHandleEntry = (ConnHandleEntry_t *) (ICall_malloc(sizeof(ConnHandleEntry_t)));
1320 if (connHandleEntry)
1322 connHandleEntry->connHandle = connHandle;
1323 List_put(&sInstance.paramUpdateList, (List_Elem *) connHandleEntry);
1327 return CHIP_NO_ERROR;
1330 /*********************************************************************
1331 * @fn EnqueueEvtHdrMsg
1333 * @brief Creates a message and puts the message in RTOS queue.
1335 * @param event - message event.
1336 * @param state - message state.
1338 status_t BLEManagerImpl::EnqueueEvtHdrMsg(uint8_t event, void * pData)
1341 QueuedEvt_t * pMsg = (QueuedEvt_t *) ICall_malloc(sizeof(QueuedEvt_t));
1342 BLEMGR_LOG("BLEMGR: EnqueueEvtHdrMsg");
1344 // Create dynamic pointer to message.
1347 pMsg->event = event;
1348 pMsg->pData = pData;
1350 // Enqueue the message.
1351 success = Util_enqueueMsg(sEventHandlerMsgQueueID, BLEManagerImpl::sSyncEvent, (uint8_t *) pMsg);
1353 return (success) ? SUCCESS : FAILURE;
1356 return bleMemAllocError;
1359 /*********************************************************************
1362 * @brief Add a device to the connected device list
1364 * @return index of the connected device list entry where the new connection
1366 * if there is no room, MAX_NUM_BLE_CONNS will be returned.
1368 uint8_t BLEManagerImpl::AddBLEConn(uint16_t connHandle)
1371 uint8_t status = bleNoResources;
1372 BLEMGR_LOG("BLEMGR: AddBLEConn");
1374 // Try to find an available entry
1375 for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
1377 if (sInstance.connList[i].connHandle == LL_CONNHANDLE_INVALID)
1379 // Found available entry to put a new connection info in
1380 sInstance.connList[i].connHandle = connHandle;
1382 // Allocate data to send through clock handler
1383 sInstance.connList[i].pParamUpdateEventData =
1384 (ClockEventData_t *) ICall_malloc(sizeof(ClockEventData_t) + sizeof(uint16_t));
1385 if (sInstance.connList[i].pParamUpdateEventData)
1387 sInstance.connList[i].pParamUpdateEventData->event = SEND_PARAM_UPDATE_EVT;
1388 *((uint16_t *) sInstance.connList[i].pParamUpdateEventData->data) = connHandle;
1390 // Create a clock object and start
1391 sInstance.connList[i].pUpdateClock = (ClockP_Struct *) ICall_malloc(sizeof(ClockP_Struct));
1393 if (sInstance.connList[i].pUpdateClock)
1395 Util_constructClock(sInstance.connList[i].pUpdateClock, ClockHandler, SEND_PARAM_UPDATE_DELAY, 0, true,
1396 (uintptr_t) sInstance.connList[i].pParamUpdateEventData);
1400 ICall_free(sInstance.connList[i].pParamUpdateEventData);
1405 status = bleMemAllocError;
1414 /*********************************************************************
1417 * @brief Remove a device from the connected device list
1419 * @return index of the connected device list entry where the new connection
1420 * info is removed from.
1421 * if connHandle is not found, MAX_NUM_BLE_CONNS will be returned.
1423 uint8_t BLEManagerImpl::RemoveBLEConn(uint16_t connHandle)
1425 uint8_t connIndex = GetBLEConnIndex(connHandle);
1426 BLEMGR_LOG("BLEMGR: RemoveBLEConn");
1428 if (connIndex != MAX_NUM_BLE_CONNS)
1430 ClockP_Struct * pUpdateClock = sInstance.connList[connIndex].pUpdateClock;
1432 if (pUpdateClock != NULL)
1434 // Stop and destruct the RTOS clock if it's still alive
1435 if (Util_isActive(pUpdateClock))
1437 Util_stopClock(pUpdateClock);
1440 // Destruct the clock object
1441 ClockP_destruct(pUpdateClock);
1442 // Free clock struct
1443 ICall_free(pUpdateClock);
1444 // Free ParamUpdateEventData
1445 ICall_free(sInstance.connList[connIndex].pParamUpdateEventData);
1447 // Clear pending update requests from paramUpdateList
1448 ClearPendingBLEParamUpdate(connHandle);
1450 // Clear Connection List Entry
1451 ClearBLEConnListEntry(connHandle);
1456 /*********************************************************************
1457 * @fn GetBLEConnIndex
1459 * @brief Find index in the connected device list by connHandle
1461 * @return the index of the entry that has the given connection handle.
1462 * if there is no match, MAX_NUM_BLE_CONNS will be returned.
1464 uint8_t BLEManagerImpl::GetBLEConnIndex(uint16_t connHandle) const
1468 BLEMGR_LOG("BLEMGR: GetBLEConnIndex");
1470 for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
1472 if (sInstance.connList[i].connHandle == connHandle)
1478 return MAX_NUM_BLE_CONNS;
1481 /*********************************************************************
1482 * @fn ClearBLEConnListEntry
1484 * @brief Find index in the connected device list by connHandle
1486 * @return the index of the entry that has the given connection handle.
1487 * if there is no match, MAX_NUM_BLE_CONNS will be returned.
1489 uint8_t BLEManagerImpl::ClearBLEConnListEntry(uint16_t connHandle)
1492 // Set to invalid connection index initially
1493 uint8_t connIndex = MAX_NUM_BLE_CONNS;
1495 BLEMGR_LOG("BLEMGR: ClearBLEConnListEntry");
1496 if (connHandle != LL_CONNHANDLE_ALL)
1498 // Get connection index from handle
1499 connIndex = GetBLEConnIndex(connHandle);
1500 if (connIndex >= MAX_NUM_BLE_CONNS)
1502 return bleInvalidRange;
1506 // Clear specific handle or all handles
1507 for (i = 0; i < MAX_NUM_BLE_CONNS; i++)
1509 if ((connIndex == i) || (connHandle == LL_CONNHANDLE_ALL))
1511 sInstance.connList[i].connHandle = LL_CONNHANDLE_INVALID;
1512 sInstance.connList[i].currPhy = 0;
1513 sInstance.connList[i].phyCngRq = 0;
1514 sInstance.connList[i].phyRqFailCnt = 0;
1515 sInstance.connList[i].rqPhy = 0;
1516 memset(sInstance.connList[i].rssiArr, 0, MAX_RSSI_STORE_DEPTH);
1517 sInstance.connList[i].rssiAvg = 0;
1518 sInstance.connList[i].rssiCntr = 0;
1519 sInstance.connList[i].isAutoPHYEnable = FALSE;
1520 sInstance.connList[i].mtu = 0;
1527 /*********************************************************************
1528 * @fn ClearPendingBLEParamUpdate
1530 * @brief clean pending param update request in the paramUpdateList list
1532 * @param connHandle - connection handle to clean
1536 void BLEManagerImpl::ClearPendingBLEParamUpdate(uint16_t connHandle)
1540 BLEMGR_LOG("BLEMGR: ClearPendingBLEParamUpdate");
1542 for (curr = List_head(&sInstance.paramUpdateList); curr != NULL; curr = List_next(curr))
1544 if (((ConnHandleEntry_t *) curr)->connHandle == connHandle)
1546 List_remove(&sInstance.paramUpdateList, curr);
1551 /*********************************************************************
1554 * @brief Read the current RPA from the stack and update display
1555 * if the RPA has changed.
1561 void BLEManagerImpl::UpdateBLERPA(void)
1564 BLEMGR_LOG("BLEMGR: UpdateBLERPA");
1566 // Read the current RPA.
1567 pRpaNew = GAP_GetDevAddress(FALSE);
1569 if (memcmp(pRpaNew, sInstance.rpa, B_ADDR_LEN))
1571 memcpy(sInstance.rpa, pRpaNew, B_ADDR_LEN);
1575 void BLEManagerImpl::EventHandler(void * arg)
1577 BLEMGR_LOG("BLEMGR: EventHandler");
1579 sInstance.EventHandler_init();
1585 // Waits for an event to be posted associated with the calling thread.
1586 // Note that an event associated with a thread is posted when a
1587 // message is queued to the message receive queue of the thread
1588 xQueueReceive((QueueHandle_t) BLEManagerImpl::sSyncEvent, (char *) &events, portMAX_DELAY);
1592 ICall_EntityID dest;
1593 ICall_ServiceEnum src;
1594 ICall_HciExtEvt * hcipMsg = NULL;
1596 /* Lock CHIP Stack while processing BLE Stack/App events */
1597 PlatformMgr().LockChipStack();
1599 BLEMGR_LOG("BLEMGR: EventHandler: Events received");
1600 // Fetch any available messages that might have been sent from the stack
1601 if (ICall_fetchServiceMsg(&src, &dest, (void **) &hcipMsg) == ICALL_ERRNO_SUCCESS)
1603 BLEMGR_LOG("BLEMGR: EventHandler: Stack Event");
1605 uint8 safeToDealloc = TRUE;
1607 if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == BLEManagerImpl::sSelfEntity))
1609 ICall_Stack_Event * pEvt = (ICall_Stack_Event *) hcipMsg;
1611 // Check for non-BLE stack events
1612 if (pEvt->signature != 0xffff)
1614 // Process inter-task message
1615 safeToDealloc = sInstance.ProcessStackEvent((ICall_Hdr *) hcipMsg);
1619 if (hcipMsg && safeToDealloc)
1621 ICall_freeMsg(hcipMsg);
1625 // If RTOS queue is not empty, process CHIP messages.
1626 if (events & QUEUE_EVT)
1628 BLEMGR_LOG("BLEMGR: EventHandler: App Event");
1633 pMsg = (QueuedEvt_t *) Util_dequeueMsg(BLEManagerImpl::sEventHandlerMsgQueueID);
1637 sInstance.ProcessEvtHdrMsg(pMsg);
1639 // Free the space from the message.
1649 PlatformMgr().UnlockChipStack();
1654 /* Post event to app processing loop to begin CHIP advertising */
1655 CHIP_ERROR BLEManagerImpl::DriveBLEState(void)
1657 CHIP_ERROR err = CHIP_NO_ERROR;
1658 BLEMGR_LOG("BLEMGR: DriveBLEState");
1660 if (sInstance.EnqueueEvtHdrMsg(BLEManagerIMPL_STATE_UPDATE_EVT, NULL) != SUCCESS)
1662 err = CHIP_ERROR_NO_MEMORY;
1667 /*********************************************************************
1670 * @brief GapAdv module callback
1672 * @param pMsg - message to process
1674 void BLEManagerImpl::advCallback(uint32_t event, void * pBuf, uintptr_t arg)
1676 BLEMGR_LOG("BLEMGR: advCallback");
1678 GapAdvEventData_t * pData = (GapAdvEventData_t *) ICall_malloc(sizeof(GapAdvEventData_t));
1682 pData->event = event;
1684 if (sInstance.EnqueueEvtHdrMsg(ADV_EVT, pData) != SUCCESS)
1691 void BLEManagerImpl::AdvTimeoutHandler(uintptr_t arg)
1693 BLEMGR_LOG("BLEMGR: AdvTimeoutHandler");
1695 if (sInstance.mFlags.Has(Flags::kAdvertisingEnabled))
1697 BLEMGR_LOG("BLEMGR: AdvTimeoutHandler ble adv 15 minute timeout");
1699 sInstance.mFlags.Clear(Flags::kAdvertisingEnabled);
1700 sInstance.mFlags.Set(Flags::kFastAdvertisingEnabled);
1702 /* Send event to process state change request */
1707 void BLEManagerImpl::ClockHandler(uintptr_t arg)
1709 ClockEventData_t * pData = (ClockEventData_t *) arg;
1710 BLEMGR_LOG("BLEMGR: ClockHandler");
1712 if (pData->event == READ_RPA_EVT)
1714 BLEMGR_LOG("BLEMGR: ClockHandler RPA EVT");
1715 // Start the next period
1716 Util_startClock(&sInstance.clkRpaRead);
1718 // Post event to read the current RPA
1719 sInstance.EnqueueEvtHdrMsg(READ_RPA_EVT, NULL);
1721 else if (pData->event == SEND_PARAM_UPDATE_EVT)
1723 BLEMGR_LOG("BLEMGR: ClockHandler PARAM UPDATE EVT");
1724 // Send message to app
1725 if (sInstance.EnqueueEvtHdrMsg(SEND_PARAM_UPDATE_EVT, pData) != SUCCESS)
1732 /*********************************************************************
1733 * @fn CHIPoBLEProfile_charValueChangeCB
1735 * @brief Callback from CHIPoBLE Profile indicating a characteristic
1737 * Calling context (BLE Stack Task)
1739 * @param paramId - parameter Id of the value that was changed.
1743 void BLEManagerImpl::CHIPoBLEProfile_charValueChangeCB(uint8_t paramId, uint16_t len, uint16_t connHandle)
1745 CHIPoBLEProfChgEvt_t * pValue = (CHIPoBLEProfChgEvt_t *) ICall_malloc(sizeof(CHIPoBLEProfChgEvt_t));
1746 BLEMGR_LOG("BLEMGR: CHIPoBLEProfile_charValueChangeCB");
1750 pValue->paramId = paramId;
1752 pValue->connHandle = connHandle;
1754 if (sInstance.EnqueueEvtHdrMsg(CHIPOBLE_CHAR_CHANGE_EVT, pValue) != SUCCESS)
1761 /*********************************************************************
1762 * @fn RemoteDisplay_passcodeCb
1764 * @brief Passcode callback.
1768 void BLEManagerImpl::PasscodeCb(uint8_t * pDeviceAddr, uint16_t connHandle, uint8_t uiInputs, uint8_t uiOutputs,
1769 uint32_t numComparison)
1771 PasscodeData_t * pData = (PasscodeData_t *) ICall_malloc(sizeof(PasscodeData_t));
1773 // Allocate space for the passcode event.
1776 pData->connHandle = connHandle;
1777 memcpy(pData->deviceAddr, pDeviceAddr, B_ADDR_LEN);
1778 pData->uiInputs = uiInputs;
1779 pData->uiOutputs = uiOutputs;
1780 pData->numComparison = numComparison;
1782 // Enqueue the event.
1783 if (sInstance.EnqueueEvtHdrMsg(PASSCODE_EVT, pData) != SUCCESS)
1790 /*********************************************************************
1793 * @brief Pairing state callback.
1797 void BLEManagerImpl::PairStateCb(uint16_t connHandle, uint8_t state, uint8_t status)
1799 PairStateData_t * pData = (PairStateData_t *) ICall_malloc(sizeof(PairStateData_t));
1801 // Allocate space for the event data.
1804 pData->state = state;
1805 pData->connHandle = connHandle;
1806 pData->status = status;
1809 if (sInstance.EnqueueEvtHdrMsg(PAIR_STATE_EVT, pData) != SUCCESS)
1816 /*******************************************************************************
1819 * @brief This is the Application's callback handler for asserts raised
1820 * in the stack. When EXT_HAL_ASSERT is defined in the Stack
1821 * project this function will be called when an assert is raised,
1822 * and can be used to observe or trap a violation from expected
1825 * As an example, for Heap allocation failures the Stack will raise
1826 * HAL_ASSERT_CAUSE_OUT_OF_MEMORY as the assertCause and
1827 * HAL_ASSERT_SUBCAUSE_NONE as the assertSubcause. An application
1828 * developer could trap any malloc failure on the stack by calling
1829 * HAL_ASSERT_SPINLOCK under the matching case.
1831 * An application developer is encouraged to extend this function
1832 * for use by their own application. To do this, add hal_assert.c
1833 * to your project workspace, the path to hal_assert.h (this can
1834 * be found on the stack side). Asserts are raised by including
1835 * hal_assert.h and using macro HAL_ASSERT(cause) to raise an
1836 * assert with argument assertCause. the assertSubcause may be
1837 * optionally set by macro HAL_ASSERT_SET_SUBCAUSE(subCause) prior
1838 * to asserting the cause it describes. More information is
1839 * available in hal_assert.h.
1843 * @param assertCause - Assert cause as defined in hal_assert.h.
1844 * @param assertSubcause - Optional assert subcause (see hal_assert.h).
1852 void BLEManagerImpl::AssertHandler(uint8 assertCause, uint8 assertSubcause)
1854 // check the assert cause
1855 switch (assertCause)
1857 case HAL_ASSERT_CAUSE_OUT_OF_MEMORY:
1861 case HAL_ASSERT_CAUSE_INTERNAL_ERROR:
1862 // check the subcause
1863 if (assertSubcause == HAL_ASSERT_SUBCAUSE_FW_INERNAL_ERROR)
1872 case HAL_ASSERT_CAUSE_ICALL_ABORT:
1875 case HAL_ASSERT_CAUSE_ICALL_TIMEOUT:
1878 case HAL_ASSERT_CAUSE_WRONG_API_CALL:
1888 } // namespace Internal
1889 } // namespace DeviceLayer
1892 #endif /* CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE */