3 * Copyright (c) 2020-2021 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
20 * Provides an implementation of the BLEManager singleton object
21 * for the QPG6100 platform.
23 /* this file behaves like a config.h, comes first */
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
26 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
28 #include <ble/BleUUID.h>
29 #include <ble/CHIPBleServiceData.h>
30 #include <platform/internal/BLEManager.h>
32 #include <support/CodeUtils.h>
33 #include <support/logging/CHIPLogging.h>
35 using namespace ::chip;
36 using namespace ::chip::Ble;
37 using namespace ::chip::System;
40 namespace DeviceLayer {
45 // Advertising data content definitions
46 #define CHIP_ADV_DATA_TYPE_FLAGS 0x01
47 #define CHIP_ADV_DATA_TYPE_UUID 0x03
48 #define CHIP_ADV_DATA_FLAGS 0x06
49 #define CHIP_ADV_DATA_TYPE_NAME 0x09
50 #define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
52 #define CHIP_ADV_SHORT_UUID_LEN 2
53 #define CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 0xFEAF
55 // Full service UUID - CHIP_BLE_SVC_ID - taken from BleUUID.h header
56 const ChipBleUUID chipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
59 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
62 } // unnamed namespace
64 BLEManagerImpl BLEManagerImpl::sInstance;
66 CHIP_ERROR BLEManagerImpl::_Init()
70 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
71 mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
72 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
74 for (int i = 0; i < kMaxConnections; i++)
76 mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
79 // Initialize the CHIP BleLayer.
80 err = BleLayer::Init(this, this, &SystemLayer);
83 appCbacks.stackCback = ExternalCbHandler;
84 appCbacks.chrReadCback = HandleTXCharRead;
85 appCbacks.chrWriteCback = HandleRXCharWrite;
86 appCbacks.cccCback = _handleTXCharCCCDWrite;
87 qvCHIP_BleInit(&appCbacks);
89 PlatformMgr().ScheduleWork(DriveBLEState, 0);
91 ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete");
96 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
98 CHIP_ERROR err = CHIP_NO_ERROR;
100 VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
101 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
103 if (val != mServiceMode)
106 PlatformMgr().ScheduleWork(DriveBLEState, 0);
113 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
115 CHIP_ERROR err = CHIP_NO_ERROR;
117 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
119 if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
121 mFlags.Set(Flags::kAdvertisingEnabled, val);
122 PlatformMgr().ScheduleWork(DriveBLEState, 0);
129 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
133 case BLEAdvertisingMode::kFastAdvertising:
134 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
136 case BLEAdvertisingMode::kSlowAdvertising:
137 mFlags.Set(Flags::kFastAdvertisingEnabled, false);
140 return CHIP_ERROR_INVALID_ARGUMENT;
142 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
143 PlatformMgr().ScheduleWork(DriveBLEState, 0);
144 return CHIP_NO_ERROR;
147 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
151 err = MapBLEError(qvCHIP_BleGetDeviceName(buf, bufSize));
156 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
158 CHIP_ERROR err = CHIP_NO_ERROR;
160 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
162 if (devName != nullptr && devName[0] != 0)
164 err = MapBLEError(qvCHIP_BleSetDeviceName(devName));
171 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
175 // Platform specific events
176 case DeviceEventType::kCHIPoBLESubscribe: {
177 ChipDeviceEvent connEstEvent;
179 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe");
180 HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
181 connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
182 PlatformMgr().PostEvent(&connEstEvent);
186 case DeviceEventType::kCHIPoBLEUnsubscribe: {
187 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
188 HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
192 case DeviceEventType::kCHIPoBLEWriteReceived: {
193 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
194 HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
195 PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
199 case DeviceEventType::kCHIPoBLEConnectionError: {
200 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
201 HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
204 // Generic CHIP events
205 case DeviceEventType::kFabricMembershipChange:
206 case DeviceEventType::kServiceProvisioningChange:
207 case DeviceEventType::kAccountPairingChange:
209 // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
210 // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
211 // is now fully provisioned.
212 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
213 if (ConfigurationMgr().IsFullyProvisioned())
215 mFlags.Clear(Flags::kAdvertisingEnabled);
216 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
218 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
220 // Force the advertising state to be refreshed to reflect new provisioning state.
221 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
227 case DeviceEventType::kCHIPoBLEIndicateConfirm: {
228 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
229 HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
234 ChipLogProgress(DeviceLayer, "_OnPlatformEvent default: event->Type = %d", event->Type);
239 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
241 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
245 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
247 ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
251 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
253 CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
255 ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
257 err = MapBLEError(qvCHIP_BleCloseConnection(conId));
258 if (err != CHIP_NO_ERROR)
260 ChipLogError(DeviceLayer, "qvCHIP_BleCloseConnection() failed: %s", ErrorStr(err));
263 return (err == CHIP_NO_ERROR);
266 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
269 CHIP_ERROR err = MapBLEError(qvCHIP_BleGetMTU(conId, &retVal));
270 if (err != CHIP_NO_ERROR)
272 ChipLogError(DeviceLayer, "qvCHIP_BleGetMTU() failed: %s", ErrorStr(err));
278 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
279 PacketBufferHandle data)
281 CHIP_ERROR err = CHIP_NO_ERROR;
284 uint16_t dataLen = data->DataLength();
286 VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT);
287 ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE Client RX characteristic (con %u, len %u)", conId, dataLen);
289 isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_TX, charId);
290 cId = qvCHIP_BleGetHandle(isRxHandle);
292 qvCHIP_BleSendIndication(conId, cId, dataLen, data->Start());
295 if (err != CHIP_NO_ERROR)
297 ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
303 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
304 PacketBufferHandle pBuf)
306 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
310 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
311 PacketBufferHandle pBuf)
313 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
317 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
318 const ChipBleUUID * svcId, const ChipBleUUID * charId)
320 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
324 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
329 CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) const
335 case QV_STATUS_NO_ERROR: {
339 case QV_STATUS_BUFFER_TOO_SMALL: {
340 err = CHIP_ERROR_BUFFER_TOO_SMALL;
343 case QV_STATUS_INVALID_ARGUMENT: {
344 err = CHIP_ERROR_INVALID_ARGUMENT;
348 err = CHIP_ERROR_INCORRECT_STATE;
354 void BLEManagerImpl::DriveBLEState(void)
356 CHIP_ERROR err = CHIP_NO_ERROR;
358 // Perform any initialization actions that must occur after the CHIP task is running.
359 if (!mFlags.Has(Flags::kAsyncInitCompleted))
361 mFlags.Set(Flags::kAsyncInitCompleted);
363 // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
364 // disable CHIPoBLE advertising if the device is fully provisioned.
365 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
366 if (ConfigurationMgr().IsFullyProvisioned())
368 mFlags.Clear(Flags::kAdvertisingEnabled);
369 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
371 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
374 // If the application has enabled CHIPoBLE and BLE advertising...
375 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
376 mFlags.Has(Flags::kAdvertisingEnabled)
377 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
378 // and no connections are active...
379 && (mNumGAPCons == 0)
383 // Start/re-start BLE advertising if not already advertising, or if the
384 // advertising state of the underlying stack needs to be refreshed.
385 if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kAdvertisingRefreshNeeded))
387 mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
388 err = StartAdvertising();
393 // Otherwise, stop advertising if currently active.
396 err = StopAdvertising();
401 if (err != CHIP_NO_ERROR)
403 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
404 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
408 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
410 ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
413 uint8_t mDeviceNameLength = 0;
414 uint8_t mDeviceIdInfoLength = 0;
416 memset(mAdvDataBuf, 0, kMaxAdvertisementDataSetSize);
417 memset(mScanRespDataBuf, 0, kMaxAdvertisementDataSetSize);
419 err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
422 if (!mFlags.Has(Flags::kDeviceNameSet))
424 snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0);
426 mDeviceName[kMaxDeviceNameLength] = 0;
427 err = MapBLEError(qvCHIP_BleSetDeviceName(mDeviceName));
431 mDeviceNameLength = static_cast<uint8_t>(strlen(mDeviceName));
432 mDeviceIdInfoLength = sizeof(mDeviceIdInfo);
435 static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
436 static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= kMaxAdvertisementDataSetSize,
437 "Advertisement data buffer is not big enough");
439 // Fill in advertising data
441 mAdvDataBuf[index++] = 0x02; // length
442 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
443 mAdvDataBuf[index++] = CHIP_ADV_DATA_FLAGS; // AD value
445 mAdvDataBuf[index++] = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
446 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data
447 mAdvDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value
448 mAdvDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF;
449 memcpy(&mAdvDataBuf[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value
450 index = static_cast<uint8_t>(index + mDeviceIdInfoLength);
452 mAdvDataBuf[index++] = static_cast<uint8_t>(mDeviceNameLength + 1); // length
453 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_NAME; // AD type : name
454 memcpy(&mAdvDataBuf[index], mDeviceName, mDeviceNameLength); // AD value
455 index = static_cast<uint8_t>(index + mDeviceNameLength);
457 qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_ADV, index, mAdvDataBuf);
459 // Fill in scan response data
461 mScanRespDataBuf[index++] = CHIP_ADV_SHORT_UUID_LEN + 1; // AD length
462 mScanRespDataBuf[index++] = CHIP_ADV_DATA_TYPE_UUID; // AD type : uuid
463 mScanRespDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value
464 mScanRespDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF;
466 qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_SCAN, index, mScanRespDataBuf);
472 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
475 uint16_t intervalMin;
476 uint16_t intervalMax;
477 ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising");
479 err = ConfigureAdvertisingData();
482 mFlags.Set(Flags::kAdvertising);
484 if ((mNumGAPCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || mFlags.Has(Flags::kFastAdvertisingEnabled))
486 intervalMin = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
487 intervalMax = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
491 intervalMin = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
492 intervalMax = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
495 qvCHIP_BleSetAdvInterval(intervalMin, intervalMax);
497 err = MapBLEError(qvCHIP_BleStartAdvertising());
504 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
508 err = MapBLEError(qvCHIP_BleStopAdvertising());
511 // Transition to the not Advertising state...
512 if (mFlags.Has(Flags::kAdvertising))
514 mFlags.Clear(Flags::kAdvertising);
515 mFlags.Set(Flags::kFastAdvertisingEnabled, true);
517 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
519 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
520 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
521 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
522 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
524 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
526 ChipDeviceEvent advChange;
527 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
528 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
529 PlatformMgr().PostEvent(&advChange);
537 uint16_t BLEManagerImpl::_NumConnections(void)
539 uint16_t numCons = 0;
540 for (uint16_t i = 0; i < kMaxConnections; i++)
542 if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED)
550 void BLEManagerImpl::DriveBLEState(intptr_t arg)
552 sInstance.DriveBLEState();
555 void BLEManagerImpl::HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset,
556 qvCHIP_Ble_Attr_t * pAttr)
560 ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE Client RX characteristic (con %u)", connId);
562 // Send a zero-length response.
563 qvCHIP_BleWriteAttr(connId, handle, 0, &rsp);
566 void BLEManagerImpl::HandleRXCharWrite(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len,
567 uint8_t * pValue, qvCHIP_Ble_Attr_t * pAttr)
569 CHIP_ERROR err = CHIP_NO_ERROR;
571 ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client TX characteristic (con %u, len %u)", connId, len);
573 // Copy the data to a packet buffer.
574 PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(pValue, len, 0, 0);
575 VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
576 // Post an event to the Chip queue to deliver the data into the Chip stack.
578 ChipDeviceEvent event;
579 event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
580 event.CHIPoBLEWriteReceived.ConId = connId;
581 event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease();
582 PlatformMgr().PostEvent(&event);
586 if (err != CHIP_NO_ERROR)
588 ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
589 // TODO: fail connection???
593 void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt)
595 CHIP_ERROR err = CHIP_NO_ERROR;
596 bool indicationsEnabled;
598 ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", pEvt->hdr.param, 0);
600 // Determine if the client is enabling or disabling indications.
601 indicationsEnabled = (pEvt->value != 0);
603 // If the client has requested to enabled indications
604 if (indicationsEnabled)
606 // Set subcription only the first time
607 if (!IsSubscribed(pEvt->hdr.param))
609 // Record that indications have been enabled for this connection.
610 err = SetSubscribed(pEvt->hdr.param);
611 VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
618 // If indications had previously been enabled for this connection, record that they are no longer
620 UnsetSubscribed(pEvt->hdr.param);
623 // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
624 // whether the client is enabling or disabling indications.
626 ChipDeviceEvent event;
627 event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
628 event.CHIPoBLESubscribe.ConId = pEvt->hdr.param;
629 PlatformMgr().PostEvent(&event);
632 ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
635 if (err != CHIP_NO_ERROR)
637 ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
638 // TODO: fail connection???
642 /* Process DM Messages */
643 void BLEManagerImpl::HandleDmMsg(qvCHIP_Ble_DmEvt_t * pDmEvt)
645 switch (pDmEvt->hdr.event)
647 case QVCHIP_DM_RESET_CMPL_IND: {
650 case QVCHIP_DM_SCAN_START_IND: {
653 case QVCHIP_DM_SCAN_STOP_IND: {
656 case QVCHIP_DM_ADV_START_IND: {
657 if (pDmEvt->hdr.status != QVCHIP_HCI_SUCCESS)
659 ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_START_IND error: %d", (int) pDmEvt->advSetStart.hdr.status);
663 sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
665 // Transition to the Advertising state...
666 if (!sInstance.mFlags.Has(Flags::kAdvertising))
668 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
670 sInstance.mFlags.Set(Flags::kAdvertising);
672 // Post a CHIPoBLEAdvertisingChange(Started) event.
674 ChipDeviceEvent advChange;
675 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
676 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
677 PlatformMgr().PostEvent(&advChange);
682 case QVCHIP_DM_ADV_STOP_IND: {
683 if (pDmEvt->advSetStop.status != QVCHIP_HCI_SUCCESS)
685 ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_STOP_IND error: %d", (int) pDmEvt->advSetStop.status);
689 sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
691 // Transition to the not Advertising state...
692 if (sInstance.mFlags.Has(Flags::kAdvertising))
694 sInstance.mFlags.Clear(Flags::kAdvertising);
696 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
698 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
699 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
700 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
701 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
703 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
705 ChipDeviceEvent advChange;
706 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
707 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
708 PlatformMgr().PostEvent(&advChange);
713 case QVCHIP_DM_CONN_OPEN_IND: {
714 ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", pDmEvt->connOpen.hdr.param);
716 // Allocate a connection state record for the new connection.
719 // Receiving a connection stops the advertising processes. So force a refresh of the advertising
721 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
722 PlatformMgr().ScheduleWork(DriveBLEState, 0);
725 case QVCHIP_DM_CONN_CLOSE_IND: {
726 ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", pDmEvt->connClose.hdr.param,
727 pDmEvt->connClose.reason);
729 // Force a refresh of the advertising state.
735 // If this was a CHIPoBLE connection, release the associated connection state record
736 // and post an event to deliver a connection error to the CHIPoBLE layer.
737 if (UnsetSubscribed(pDmEvt->connClose.hdr.param))
739 ChipDeviceEvent event;
740 event.Type = DeviceEventType::kCHIPoBLEConnectionError;
741 event.CHIPoBLEConnectionError.ConId = pDmEvt->connClose.hdr.param;
742 switch (pDmEvt->connClose.reason)
744 case QVCHIP_HCI_ERR_REMOTE_TERMINATED:
745 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
747 case QVCHIP_HCI_ERR_LOCAL_TERMINATED:
748 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
751 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
754 PlatformMgr().PostEvent(&event);
757 mFlags.Set(Flags::kAdvertisingRefreshNeeded);
758 PlatformMgr().ScheduleWork(DriveBLEState, 0);
761 case QVCHIP_DM_CONN_UPDATE_IND: {
770 PlatformMgr().ScheduleWork(DriveBLEState, 0);
773 /* Process ATT Messages */
774 void BLEManagerImpl::HandleAttMsg(qvCHIP_Ble_AttEvt_t * pAttEvt)
776 switch (pAttEvt->hdr.event)
778 case QVCHIP_ATT_MTU_UPDATE_IND: {
781 case QVCHIP_ATTS_HANDLE_VALUE_CNF: {
782 ChipDeviceEvent event;
784 event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm;
785 event.CHIPoBLEIndicateConfirm.ConId = pAttEvt->hdr.param;
786 PlatformMgr().PostEvent(&event);
789 case QVCHIP_ATTC_FIND_BY_TYPE_VALUE_RSP:
790 case QVCHIP_ATTC_READ_BY_GROUP_TYPE_RSP:
791 case QVCHIP_ATTC_READ_BY_TYPE_RSP:
792 case QVCHIP_ATTC_FIND_INFO_RSP:
794 case QVCHIP_ATTC_READ_RSP:
796 case QVCHIP_ATTC_WRITE_RSP:
797 case QVCHIP_ATTC_WRITE_CMD_RSP:
798 case QVCHIP_ATTC_PREPARE_WRITE_RSP:
800 case QVCHIP_ATTC_EXECUTE_WRITE_RSP:
802 case QVCHIP_ATTC_HANDLE_VALUE_NTF:
803 case QVCHIP_ATTC_HANDLE_VALUE_IND:
811 void BLEManagerImpl::ExternalCbHandler(qvCHIP_Ble_MsgHdr_t * pMsg)
815 PlatformMgr().LockChipStack();
817 /* Process advertising/scanning and connection-related messages */
818 if (pMsg->event >= QVCHIP_DM_CBACK_START && pMsg->event <= QVCHIP_DM_CBACK_END)
820 ChipLogProgress(DeviceLayer, "DM event %d: status %d", pMsg->event, pMsg->status);
821 sInstance.HandleDmMsg((qvCHIP_Ble_DmEvt_t *) pMsg);
823 /* Process attribute-related messages */
824 else if (pMsg->event >= QVCHIP_ATT_CBACK_START && pMsg->event <= QVCHIP_ATT_CBACK_END)
826 ChipLogProgress(DeviceLayer, "ATT event %d: status %d", pMsg->event, pMsg->status);
827 sInstance.HandleAttMsg((qvCHIP_Ble_AttEvt_t *) pMsg);
831 ChipLogProgress(DeviceLayer, "Unknown event %d", pMsg->event);
834 PlatformMgr().UnlockChipStack();
838 CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
840 uint16_t freeIndex = kMaxConnections;
842 for (uint16_t i = 0; i < kMaxConnections; i++)
844 if (mSubscribedConIds[i] == conId)
846 return CHIP_NO_ERROR;
848 else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex)
854 if (freeIndex < kMaxConnections)
856 mSubscribedConIds[freeIndex] = conId;
857 return CHIP_NO_ERROR;
861 return CHIP_ERROR_NO_MEMORY;
865 bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
867 for (uint16_t i = 0; i < kMaxConnections; i++)
869 if (mSubscribedConIds[i] == conId)
871 mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
878 bool BLEManagerImpl::IsSubscribed(uint16_t conId)
880 if (conId != BLE_CONNECTION_UNINITIALIZED)
882 for (uint16_t i = 0; i < kMaxConnections; i++)
884 if (mSubscribedConIds[i] == conId)
893 void BLEManagerImpl::_handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event)
895 sInstance.HandleTXCharCCCDWrite(event);
898 } // namespace Internal
899 } // namespace DeviceLayer
902 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE