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 = CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? kFlag_AdvertisingEnabled : 0;
73 for (int i = 0; i < kMaxConnections; i++)
75 mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
78 // Initialize the CHIP BleLayer.
79 err = BleLayer::Init(this, this, &SystemLayer);
82 appCbacks.stackCback = ExternalCbHandler;
83 appCbacks.chrReadCback = HandleTXCharRead;
84 appCbacks.chrWriteCback = HandleRXCharWrite;
85 appCbacks.cccCback = _handleTXCharCCCDWrite;
86 qvCHIP_BleInit(&appCbacks);
88 PlatformMgr().ScheduleWork(DriveBLEState, 0);
90 ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete");
95 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
97 CHIP_ERROR err = CHIP_NO_ERROR;
99 VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
100 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
102 if (val != mServiceMode)
105 PlatformMgr().ScheduleWork(DriveBLEState, 0);
112 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
114 CHIP_ERROR err = CHIP_NO_ERROR;
116 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
118 if (GetFlag(mFlags, kFlag_AdvertisingEnabled) != val)
120 SetFlag(mFlags, kFlag_AdvertisingEnabled, val);
121 PlatformMgr().ScheduleWork(DriveBLEState, 0);
128 CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val)
130 CHIP_ERROR err = CHIP_NO_ERROR;
132 VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
134 if (GetFlag(mFlags, kFlag_FastAdvertisingEnabled) != val)
136 SetFlag(mFlags, kFlag_FastAdvertisingEnabled, val);
137 PlatformMgr().ScheduleWork(DriveBLEState, 0);
144 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
148 err = MapBLEError(qvCHIP_BleGetDeviceName(buf, bufSize));
153 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
155 CHIP_ERROR err = CHIP_NO_ERROR;
157 VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
159 if (devName != nullptr && devName[0] != 0)
161 err = MapBLEError(qvCHIP_BleSetDeviceName(devName));
168 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
172 // Platform specific events
173 case DeviceEventType::kCHIPoBLESubscribe: {
174 ChipDeviceEvent connEstEvent;
176 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe");
177 HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
178 connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
179 PlatformMgr().PostEvent(&connEstEvent);
183 case DeviceEventType::kCHIPoBLEUnsubscribe: {
184 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
185 HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
189 case DeviceEventType::kCHIPoBLEWriteReceived: {
190 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
191 HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_RX,
192 PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
196 case DeviceEventType::kCHIPoBLEConnectionError: {
197 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
198 HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
201 // Generic CHIP events
202 case DeviceEventType::kFabricMembershipChange:
203 case DeviceEventType::kServiceProvisioningChange:
204 case DeviceEventType::kAccountPairingChange:
206 // If CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled, and there is a change to the
207 // device's provisioning state, then automatically disable CHIPoBLE advertising if the device
208 // is now fully provisioned.
209 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
210 if (ConfigurationMgr().IsFullyProvisioned())
212 ClearFlag(mFlags, kFlag_AdvertisingEnabled);
213 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
215 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
217 // Force the advertising state to be refreshed to reflect new provisioning state.
218 SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
224 case DeviceEventType::kCHIPoBLEIndicateConfirm: {
225 ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
226 HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
231 ChipLogProgress(DeviceLayer, "_OnPlatformEvent default: event->Type = %d", event->Type);
236 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
238 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
242 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
244 ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
248 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
250 CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
252 ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
254 err = MapBLEError(qvCHIP_BleCloseConnection(conId));
255 if (err != CHIP_NO_ERROR)
257 ChipLogError(DeviceLayer, "qvCHIP_BleCloseConnection() failed: %s", ErrorStr(err));
260 return (err == CHIP_NO_ERROR);
263 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
266 CHIP_ERROR err = MapBLEError(qvCHIP_BleGetMTU(conId, &retVal));
267 if (err != CHIP_NO_ERROR)
269 ChipLogError(DeviceLayer, "qvCHIP_BleGetMTU() failed: %s", ErrorStr(err));
275 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
276 PacketBufferHandle data)
278 CHIP_ERROR err = CHIP_NO_ERROR;
281 uint16_t dataLen = data->DataLength();
283 VerifyOrExit(IsSubscribed(conId), err = CHIP_ERROR_INVALID_ARGUMENT);
284 ChipLogDetail(DeviceLayer, "Sending indication for CHIPoBLE Client RX characteristic (con %u, len %u)", conId, dataLen);
286 isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_TX, charId);
287 cId = qvCHIP_BleGetHandle(isRxHandle);
289 qvCHIP_BleSendIndication(conId, cId, dataLen, data->Start());
292 if (err != CHIP_NO_ERROR)
294 ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
300 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
301 PacketBufferHandle pBuf)
303 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
307 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
308 PacketBufferHandle pBuf)
310 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
314 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
315 const ChipBleUUID * svcId, const ChipBleUUID * charId)
317 ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
321 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
326 CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) const
332 case QV_STATUS_NO_ERROR: {
336 case QV_STATUS_BUFFER_TOO_SMALL: {
337 err = CHIP_ERROR_BUFFER_TOO_SMALL;
340 case QV_STATUS_INVALID_ARGUMENT: {
341 err = CHIP_ERROR_INVALID_ARGUMENT;
345 err = CHIP_ERROR_INCORRECT_STATE;
351 void BLEManagerImpl::DriveBLEState(void)
353 CHIP_ERROR err = CHIP_NO_ERROR;
355 // Perform any initialization actions that must occur after the CHIP task is running.
356 if (!GetFlag(mFlags, kFlag_AsyncInitCompleted))
358 SetFlag(mFlags, kFlag_AsyncInitCompleted);
360 // If CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED is enabled,
361 // disable CHIPoBLE advertising if the device is fully provisioned.
362 #if CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
363 if (ConfigurationMgr().IsFullyProvisioned())
365 ClearFlag(mFlags, kFlag_AdvertisingEnabled);
366 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
368 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
371 // If the application has enabled CHIPoBLE and BLE advertising...
372 if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled &&
373 GetFlag(mFlags, kFlag_AdvertisingEnabled)
374 #if CHIP_DEVICE_CONFIG_CHIPOBLE_SINGLE_CONNECTION
375 // and no connections are active...
376 && (mNumGAPCons == 0)
380 // Start/re-start BLE advertising if not already advertising, or if the
381 // advertising state of the underlying stack needs to be refreshed.
382 if (!GetFlag(mFlags, kFlag_Advertising) || GetFlag(mFlags, kFlag_AdvertisingRefreshNeeded))
384 err = StartAdvertising();
389 // Otherwise, stop advertising if currently active.
392 err = StopAdvertising();
397 if (err != CHIP_NO_ERROR)
399 ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
400 mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
404 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
406 ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
409 uint8_t mDeviceNameLength = 0;
410 uint8_t mDeviceIdInfoLength = 0;
412 memset(mAdvDataBuf, 0, kMaxAdvertisementDataSetSize);
413 memset(mScanRespDataBuf, 0, kMaxAdvertisementDataSetSize);
415 err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
418 if (!GetFlag(mFlags, kFlag_DeviceNameSet))
420 snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0);
422 mDeviceName[kMaxDeviceNameLength] = 0;
423 err = MapBLEError(qvCHIP_BleSetDeviceName(mDeviceName));
427 mDeviceNameLength = static_cast<uint8_t>(strlen(mDeviceName));
428 mDeviceIdInfoLength = sizeof(mDeviceIdInfo);
431 static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
432 static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= kMaxAdvertisementDataSetSize,
433 "Advertisement data buffer is not big enough");
435 // Fill in advertising data
437 mAdvDataBuf[index++] = 0x02; // length
438 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_FLAGS; // AD type : flags
439 mAdvDataBuf[index++] = CHIP_ADV_DATA_FLAGS; // AD value
441 mAdvDataBuf[index++] = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
442 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA; // AD type : Service Data
443 mAdvDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value
444 mAdvDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF;
445 memcpy(&mAdvDataBuf[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value
446 index = static_cast<uint8_t>(index + mDeviceIdInfoLength);
448 mAdvDataBuf[index++] = static_cast<uint8_t>(mDeviceNameLength + 1); // length
449 mAdvDataBuf[index++] = CHIP_ADV_DATA_TYPE_NAME; // AD type : name
450 memcpy(&mAdvDataBuf[index], mDeviceName, mDeviceNameLength); // AD value
451 index = static_cast<uint8_t>(index + mDeviceNameLength);
453 qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_ADV, index, mAdvDataBuf);
455 // Fill in scan response data
457 mScanRespDataBuf[index++] = CHIP_ADV_SHORT_UUID_LEN + 1; // AD length
458 mScanRespDataBuf[index++] = CHIP_ADV_DATA_TYPE_UUID; // AD type : uuid
459 mScanRespDataBuf[index++] = CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 & 0xFF; // AD value
460 mScanRespDataBuf[index++] = (CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 >> 8) & 0xFF;
462 qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_SCAN, index, mScanRespDataBuf);
468 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
472 ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising");
474 err = ConfigureAdvertisingData();
477 SetFlag(mFlags, kFlag_Advertising, true);
479 interval = ((mNumGAPCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || GetFlag(mFlags, kFlag_FastAdvertisingEnabled))
480 ? CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL
481 : CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL;
483 // Minimum and maximum interval are the same
484 qvCHIP_BleSetAdvInterval(interval, interval);
486 err = MapBLEError(qvCHIP_BleStartAdvertising());
493 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
497 err = MapBLEError(qvCHIP_BleStopAdvertising());
500 // Transition to the not Advertising state...
501 if (GetFlag(mFlags, kFlag_Advertising))
503 ClearFlag(mFlags, kFlag_Advertising);
505 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
507 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
508 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
509 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
510 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
512 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
514 ChipDeviceEvent advChange;
515 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
516 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
517 PlatformMgr().PostEvent(&advChange);
525 uint16_t BLEManagerImpl::_NumConnections(void)
527 uint16_t numCons = 0;
528 for (uint16_t i = 0; i < kMaxConnections; i++)
530 if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED)
538 void BLEManagerImpl::DriveBLEState(intptr_t arg)
540 sInstance.DriveBLEState();
543 void BLEManagerImpl::HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset,
544 qvCHIP_Ble_Attr_t * pAttr)
548 ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE Client RX characteristic (con %u)", connId);
550 // Send a zero-length response.
551 qvCHIP_BleWriteAttr(connId, handle, 0, &rsp);
554 void BLEManagerImpl::HandleRXCharWrite(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset, uint16_t len,
555 uint8_t * pValue, qvCHIP_Ble_Attr_t * pAttr)
557 CHIP_ERROR err = CHIP_NO_ERROR;
559 ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client TX characteristic (con %u, len %u)", connId, len);
561 // Copy the data to a packet buffer.
562 PacketBufferHandle buf = System::PacketBufferHandle::NewWithData(pValue, len, 0, 0);
563 VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
564 // Post an event to the Chip queue to deliver the data into the Chip stack.
566 ChipDeviceEvent event;
567 event.Type = DeviceEventType::kCHIPoBLEWriteReceived;
568 event.CHIPoBLEWriteReceived.ConId = connId;
569 event.CHIPoBLEWriteReceived.Data = std::move(buf).UnsafeRelease();
570 PlatformMgr().PostEvent(&event);
574 if (err != CHIP_NO_ERROR)
576 ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
577 // TODO: fail connection???
581 void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt)
583 CHIP_ERROR err = CHIP_NO_ERROR;
584 bool indicationsEnabled;
586 ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", pEvt->hdr.param, 0);
588 // Determine if the client is enabling or disabling indications.
589 indicationsEnabled = (pEvt->value != 0);
591 // If the client has requested to enabled indications
592 if (indicationsEnabled)
594 // Set subcription only the first time
595 if (!IsSubscribed(pEvt->hdr.param))
597 // Record that indications have been enabled for this connection.
598 err = SetSubscribed(pEvt->hdr.param);
599 VerifyOrExit(err != CHIP_ERROR_NO_MEMORY, err = CHIP_NO_ERROR);
606 // If indications had previously been enabled for this connection, record that they are no longer
608 UnsetSubscribed(pEvt->hdr.param);
611 // Post an event to the Chip queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
612 // whether the client is enabling or disabling indications.
614 ChipDeviceEvent event;
615 event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
616 event.CHIPoBLESubscribe.ConId = pEvt->hdr.param;
617 PlatformMgr().PostEvent(&event);
620 ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
623 if (err != CHIP_NO_ERROR)
625 ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
626 // TODO: fail connection???
630 /* Process DM Messages */
631 void BLEManagerImpl::HandleDmMsg(qvCHIP_Ble_DmEvt_t * pDmEvt)
633 switch (pDmEvt->hdr.event)
635 case QVCHIP_DM_RESET_CMPL_IND: {
638 case QVCHIP_DM_SCAN_START_IND: {
641 case QVCHIP_DM_SCAN_STOP_IND: {
644 case QVCHIP_DM_ADV_START_IND: {
645 if (pDmEvt->hdr.status != QVCHIP_HCI_SUCCESS)
647 ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_START_IND error: %d", (int) pDmEvt->advSetStart.hdr.status);
651 ClearFlag(sInstance.mFlags, kFlag_AdvertisingRefreshNeeded);
653 // Transition to the Advertising state...
654 if (!GetFlag(sInstance.mFlags, kFlag_Advertising))
656 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
658 SetFlag(sInstance.mFlags, kFlag_Advertising, true);
660 // Post a CHIPoBLEAdvertisingChange(Started) event.
662 ChipDeviceEvent advChange;
663 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
664 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
665 PlatformMgr().PostEvent(&advChange);
670 case QVCHIP_DM_ADV_STOP_IND: {
671 if (pDmEvt->advSetStop.status != QVCHIP_HCI_SUCCESS)
673 ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_STOP_IND error: %d", (int) pDmEvt->advSetStop.status);
677 ClearFlag(sInstance.mFlags, kFlag_AdvertisingRefreshNeeded);
679 // Transition to the not Advertising state...
680 if (GetFlag(sInstance.mFlags, kFlag_Advertising))
682 ClearFlag(sInstance.mFlags, kFlag_Advertising);
684 ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
686 // Directly inform the ThreadStackManager that CHIPoBLE advertising has stopped.
687 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
688 ThreadStackMgr().OnCHIPoBLEAdvertisingStop();
689 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
691 // Post a CHIPoBLEAdvertisingChange(Stopped) event.
693 ChipDeviceEvent advChange;
694 advChange.Type = DeviceEventType::kCHIPoBLEAdvertisingChange;
695 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
696 PlatformMgr().PostEvent(&advChange);
701 case QVCHIP_DM_CONN_OPEN_IND: {
702 ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", pDmEvt->connOpen.hdr.param);
704 // Allocate a connection state record for the new connection.
707 // Receiving a connection stops the advertising processes. So force a refresh of the advertising
709 SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
710 PlatformMgr().ScheduleWork(DriveBLEState, 0);
713 case QVCHIP_DM_CONN_CLOSE_IND: {
714 ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", pDmEvt->connClose.hdr.param,
715 pDmEvt->connClose.reason);
717 // Force a refresh of the advertising state.
723 // If this was a CHIPoBLE connection, release the associated connection state record
724 // and post an event to deliver a connection error to the CHIPoBLE layer.
725 if (UnsetSubscribed(pDmEvt->connClose.hdr.param))
727 ChipDeviceEvent event;
728 event.Type = DeviceEventType::kCHIPoBLEConnectionError;
729 event.CHIPoBLEConnectionError.ConId = pDmEvt->connClose.hdr.param;
730 switch (pDmEvt->connClose.reason)
732 case QVCHIP_HCI_ERR_REMOTE_TERMINATED:
733 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
735 case QVCHIP_HCI_ERR_LOCAL_TERMINATED:
736 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
739 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
742 PlatformMgr().PostEvent(&event);
745 SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
746 PlatformMgr().ScheduleWork(DriveBLEState, 0);
749 case QVCHIP_DM_CONN_UPDATE_IND: {
758 PlatformMgr().ScheduleWork(DriveBLEState, 0);
761 /* Process ATT Messages */
762 void BLEManagerImpl::HandleAttMsg(qvCHIP_Ble_AttEvt_t * pAttEvt)
764 switch (pAttEvt->hdr.event)
766 case QVCHIP_ATT_MTU_UPDATE_IND: {
769 case QVCHIP_ATTS_HANDLE_VALUE_CNF: {
770 ChipDeviceEvent event;
772 event.Type = DeviceEventType::kCHIPoBLEIndicateConfirm;
773 event.CHIPoBLEIndicateConfirm.ConId = pAttEvt->hdr.param;
774 PlatformMgr().PostEvent(&event);
777 case QVCHIP_ATTC_FIND_BY_TYPE_VALUE_RSP:
778 case QVCHIP_ATTC_READ_BY_GROUP_TYPE_RSP:
779 case QVCHIP_ATTC_READ_BY_TYPE_RSP:
780 case QVCHIP_ATTC_FIND_INFO_RSP:
782 case QVCHIP_ATTC_READ_RSP:
784 case QVCHIP_ATTC_WRITE_RSP:
785 case QVCHIP_ATTC_WRITE_CMD_RSP:
786 case QVCHIP_ATTC_PREPARE_WRITE_RSP:
788 case QVCHIP_ATTC_EXECUTE_WRITE_RSP:
790 case QVCHIP_ATTC_HANDLE_VALUE_NTF:
791 case QVCHIP_ATTC_HANDLE_VALUE_IND:
799 void BLEManagerImpl::ExternalCbHandler(qvCHIP_Ble_MsgHdr_t * pMsg)
803 PlatformMgr().LockChipStack();
805 /* Process advertising/scanning and connection-related messages */
806 if (pMsg->event >= QVCHIP_DM_CBACK_START && pMsg->event <= QVCHIP_DM_CBACK_END)
808 ChipLogProgress(DeviceLayer, "DM event %d: status %d", pMsg->event, pMsg->status);
809 sInstance.HandleDmMsg((qvCHIP_Ble_DmEvt_t *) pMsg);
811 /* Process attribute-related messages */
812 else if (pMsg->event >= QVCHIP_ATT_CBACK_START && pMsg->event <= QVCHIP_ATT_CBACK_END)
814 ChipLogProgress(DeviceLayer, "ATT event %d: status %d", pMsg->event, pMsg->status);
815 sInstance.HandleAttMsg((qvCHIP_Ble_AttEvt_t *) pMsg);
819 ChipLogProgress(DeviceLayer, "Unknown event %d", pMsg->event);
822 PlatformMgr().UnlockChipStack();
826 CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
828 uint16_t freeIndex = kMaxConnections;
830 for (uint16_t i = 0; i < kMaxConnections; i++)
832 if (mSubscribedConIds[i] == conId)
834 return CHIP_NO_ERROR;
836 else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex)
842 if (freeIndex < kMaxConnections)
844 mSubscribedConIds[freeIndex] = conId;
845 return CHIP_NO_ERROR;
849 return CHIP_ERROR_NO_MEMORY;
853 bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
855 for (uint16_t i = 0; i < kMaxConnections; i++)
857 if (mSubscribedConIds[i] == conId)
859 mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
866 bool BLEManagerImpl::IsSubscribed(uint16_t conId)
868 if (conId != BLE_CONNECTION_UNINITIALIZED)
870 for (uint16_t i = 0; i < kMaxConnections; i++)
872 if (mSubscribedConIds[i] == conId)
881 void BLEManagerImpl::_handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event)
883 sInstance.HandleTXCharCCCDWrite(event);
886 } // namespace Internal
887 } // namespace DeviceLayer
890 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE