b831e9bf71d2dbf300629fe180c6ba5273838d1c
[platform/upstream/connectedhomeip.git] / src / platform / qpg6100 / BLEManagerImpl.cpp
1 /*
2  *
3  *    Copyright (c) 2020-2021 Project CHIP Authors
4  *
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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 /**
19  *    @file
20  *          Provides an implementation of the BLEManager singleton object
21  *          for the QPG6100 platform.
22  */
23 /* this file behaves like a config.h, comes first */
24 #include <platform/internal/CHIPDeviceLayerInternal.h>
25
26 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
27
28 #include <ble/BleUUID.h>
29 #include <ble/CHIPBleServiceData.h>
30 #include <platform/internal/BLEManager.h>
31
32 #include <support/CodeUtils.h>
33 #include <support/logging/CHIPLogging.h>
34
35 using namespace ::chip;
36 using namespace ::chip::Ble;
37 using namespace ::chip::System;
38
39 namespace chip {
40 namespace DeviceLayer {
41 namespace Internal {
42
43 namespace {
44
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
51
52 #define CHIP_ADV_SHORT_UUID_LEN 2
53 #define CHIP_ADV_CHIP_OVER_BLE_SERVICE_UUID16 0xFEAF
54
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,
57                                                  0x9D, 0x11 } };
58
59 const ChipBleUUID chipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
60                                                  0x9D, 0x12 } };
61
62 } // unnamed namespace
63
64 BLEManagerImpl BLEManagerImpl::sInstance;
65
66 CHIP_ERROR BLEManagerImpl::_Init()
67 {
68     CHIP_ERROR err;
69
70     mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
71     mFlags       = CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? kFlag_AdvertisingEnabled : 0;
72     mNumGAPCons  = 0;
73     for (int i = 0; i < kMaxConnections; i++)
74     {
75         mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
76     }
77
78     // Initialize the CHIP BleLayer.
79     err = BleLayer::Init(this, this, &SystemLayer);
80     SuccessOrExit(err);
81
82     appCbacks.stackCback    = ExternalCbHandler;
83     appCbacks.chrReadCback  = HandleTXCharRead;
84     appCbacks.chrWriteCback = HandleRXCharWrite;
85     appCbacks.cccCback      = _handleTXCharCCCDWrite;
86     qvCHIP_BleInit(&appCbacks);
87
88     PlatformMgr().ScheduleWork(DriveBLEState, 0);
89 exit:
90     ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete");
91
92     return err;
93 }
94
95 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
96 {
97     CHIP_ERROR err = CHIP_NO_ERROR;
98
99     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
100     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
101
102     if (val != mServiceMode)
103     {
104         mServiceMode = val;
105         PlatformMgr().ScheduleWork(DriveBLEState, 0);
106     }
107
108 exit:
109     return err;
110 }
111
112 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
113 {
114     CHIP_ERROR err = CHIP_NO_ERROR;
115
116     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
117
118     if (GetFlag(mFlags, kFlag_AdvertisingEnabled) != val)
119     {
120         SetFlag(mFlags, kFlag_AdvertisingEnabled, val);
121         PlatformMgr().ScheduleWork(DriveBLEState, 0);
122     }
123
124 exit:
125     return err;
126 }
127
128 CHIP_ERROR BLEManagerImpl::_SetFastAdvertisingEnabled(bool val)
129 {
130     CHIP_ERROR err = CHIP_NO_ERROR;
131
132     VerifyOrExit(mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
133
134     if (GetFlag(mFlags, kFlag_FastAdvertisingEnabled) != val)
135     {
136         SetFlag(mFlags, kFlag_FastAdvertisingEnabled, val);
137         PlatformMgr().ScheduleWork(DriveBLEState, 0);
138     }
139
140 exit:
141     return err;
142 }
143
144 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
145 {
146     CHIP_ERROR err;
147
148     err = MapBLEError(qvCHIP_BleGetDeviceName(buf, bufSize));
149
150     return err;
151 }
152
153 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
154 {
155     CHIP_ERROR err = CHIP_NO_ERROR;
156
157     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
158
159     if (devName != nullptr && devName[0] != 0)
160     {
161         err = MapBLEError(qvCHIP_BleSetDeviceName(devName));
162     }
163
164 exit:
165     return err;
166 }
167
168 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
169 {
170     switch (event->Type)
171     {
172     // Platform specific events
173     case DeviceEventType::kCHIPoBLESubscribe: {
174         ChipDeviceEvent connEstEvent;
175
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);
180     }
181     break;
182
183     case DeviceEventType::kCHIPoBLEUnsubscribe: {
184         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
185         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
186     }
187     break;
188
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));
193     }
194     break;
195
196     case DeviceEventType::kCHIPoBLEConnectionError: {
197         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
198         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
199     }
200     break;
201     // Generic CHIP events
202     case DeviceEventType::kFabricMembershipChange:
203     case DeviceEventType::kServiceProvisioningChange:
204     case DeviceEventType::kAccountPairingChange:
205
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())
211         {
212             ClearFlag(mFlags, kFlag_AdvertisingEnabled);
213             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
214         }
215 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
216
217         // Force the advertising state to be refreshed to reflect new provisioning state.
218         SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
219
220         DriveBLEState();
221
222         break;
223
224     case DeviceEventType::kCHIPoBLEIndicateConfirm: {
225         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
226         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
227     }
228     break;
229
230     default:
231         ChipLogProgress(DeviceLayer, "_OnPlatformEvent default:  event->Type = %d", event->Type);
232         break;
233     }
234 }
235
236 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
237 {
238     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
239     return false;
240 }
241
242 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
243 {
244     ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
245     return false;
246 }
247
248 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
249 {
250     CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
251
252     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
253
254     err = MapBLEError(qvCHIP_BleCloseConnection(conId));
255     if (err != CHIP_NO_ERROR)
256     {
257         ChipLogError(DeviceLayer, "qvCHIP_BleCloseConnection() failed: %s", ErrorStr(err));
258     }
259
260     return (err == CHIP_NO_ERROR);
261 }
262
263 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
264 {
265     uint16_t retVal = 0;
266     CHIP_ERROR err  = MapBLEError(qvCHIP_BleGetMTU(conId, &retVal));
267     if (err != CHIP_NO_ERROR)
268     {
269         ChipLogError(DeviceLayer, "qvCHIP_BleGetMTU() failed: %s", ErrorStr(err));
270     }
271
272     return retVal;
273 }
274
275 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
276                                     PacketBufferHandle data)
277 {
278     CHIP_ERROR err = CHIP_NO_ERROR;
279     bool isRxHandle;
280     uint16_t cId;
281     uint16_t dataLen = data->DataLength();
282
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);
285
286     isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_TX, charId);
287     cId        = qvCHIP_BleGetHandle(isRxHandle);
288
289     qvCHIP_BleSendIndication(conId, cId, dataLen, data->Start());
290
291 exit:
292     if (err != CHIP_NO_ERROR)
293     {
294         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
295         return false;
296     }
297     return true;
298 }
299
300 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
301                                       PacketBufferHandle pBuf)
302 {
303     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
304     return false;
305 }
306
307 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
308                                      PacketBufferHandle pBuf)
309 {
310     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
311     return false;
312 }
313
314 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
315                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
316 {
317     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
318     return false;
319 }
320
321 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
322 {
323     // Nothing to do
324 }
325
326 CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) const
327 {
328     CHIP_ERROR err;
329
330     switch (bleErr)
331     {
332     case QV_STATUS_NO_ERROR: {
333         err = CHIP_NO_ERROR;
334         break;
335     }
336     case QV_STATUS_BUFFER_TOO_SMALL: {
337         err = CHIP_ERROR_BUFFER_TOO_SMALL;
338         break;
339     }
340     case QV_STATUS_INVALID_ARGUMENT: {
341         err = CHIP_ERROR_INVALID_ARGUMENT;
342         break;
343     }
344     default: {
345         err = CHIP_ERROR_INCORRECT_STATE;
346     }
347     }
348     return err;
349 }
350
351 void BLEManagerImpl::DriveBLEState(void)
352 {
353     CHIP_ERROR err = CHIP_NO_ERROR;
354
355     // Perform any initialization actions that must occur after the CHIP task is running.
356     if (!GetFlag(mFlags, kFlag_AsyncInitCompleted))
357     {
358         SetFlag(mFlags, kFlag_AsyncInitCompleted);
359
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())
364         {
365             ClearFlag(mFlags, kFlag_AdvertisingEnabled);
366             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
367         }
368 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
369     }
370
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)
377 #endif
378     )
379     {
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))
383         {
384             err = StartAdvertising();
385             SuccessOrExit(err);
386         }
387     }
388
389     // Otherwise, stop advertising if currently active.
390     else
391     {
392         err = StopAdvertising();
393         SuccessOrExit(err);
394     }
395
396 exit:
397     if (err != CHIP_NO_ERROR)
398     {
399         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
400         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
401     }
402 }
403
404 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
405 {
406     ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
407     CHIP_ERROR err;
408     uint8_t index               = 0;
409     uint8_t mDeviceNameLength   = 0;
410     uint8_t mDeviceIdInfoLength = 0;
411
412     memset(mAdvDataBuf, 0, kMaxAdvertisementDataSetSize);
413     memset(mScanRespDataBuf, 0, kMaxAdvertisementDataSetSize);
414
415     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
416     SuccessOrExit(err);
417
418     if (!GetFlag(mFlags, kFlag_DeviceNameSet))
419     {
420         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0);
421
422         mDeviceName[kMaxDeviceNameLength] = 0;
423         err                               = MapBLEError(qvCHIP_BleSetDeviceName(mDeviceName));
424         SuccessOrExit(err);
425     }
426
427     mDeviceNameLength   = static_cast<uint8_t>(strlen(mDeviceName));
428     mDeviceIdInfoLength = sizeof(mDeviceIdInfo);
429
430     // Check sizes
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");
434
435     // Fill in advertising data
436     index                = 0;
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
440
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);
447
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);
452
453     qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_ADV, index, mAdvDataBuf);
454
455     // Fill in scan response data
456     index                     = 0;
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;
461
462     qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_SCAN, index, mScanRespDataBuf);
463
464 exit:
465     return err;
466 }
467
468 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
469 {
470     CHIP_ERROR err;
471     uint16_t interval;
472     ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising");
473
474     err = ConfigureAdvertisingData();
475     SuccessOrExit(err);
476
477     SetFlag(mFlags, kFlag_Advertising, true);
478
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;
482
483     // Minimum and maximum interval are the same
484     qvCHIP_BleSetAdvInterval(interval, interval);
485
486     err = MapBLEError(qvCHIP_BleStartAdvertising());
487     SuccessOrExit(err);
488
489 exit:
490     return err;
491 }
492
493 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
494 {
495     CHIP_ERROR err;
496
497     err = MapBLEError(qvCHIP_BleStopAdvertising());
498     SuccessOrExit(err);
499
500     // Transition to the not Advertising state...
501     if (GetFlag(mFlags, kFlag_Advertising))
502     {
503         ClearFlag(mFlags, kFlag_Advertising);
504
505         ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
506
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
511
512         // Post a CHIPoBLEAdvertisingChange(Stopped) event.
513         {
514             ChipDeviceEvent advChange;
515             advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
516             advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
517             PlatformMgr().PostEvent(&advChange);
518         }
519     }
520
521 exit:
522     return err;
523 }
524
525 uint16_t BLEManagerImpl::_NumConnections(void)
526 {
527     uint16_t numCons = 0;
528     for (uint16_t i = 0; i < kMaxConnections; i++)
529     {
530         if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED)
531         {
532             numCons++;
533         }
534     }
535     return numCons;
536 }
537
538 void BLEManagerImpl::DriveBLEState(intptr_t arg)
539 {
540     sInstance.DriveBLEState();
541 }
542
543 void BLEManagerImpl::HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset,
544                                       qvCHIP_Ble_Attr_t * pAttr)
545 {
546     uint8_t rsp = 0;
547
548     ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE Client RX characteristic (con %u)", connId);
549
550     // Send a zero-length response.
551     qvCHIP_BleWriteAttr(connId, handle, 0, &rsp);
552 }
553
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)
556 {
557     CHIP_ERROR err = CHIP_NO_ERROR;
558
559     ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client TX characteristic (con %u, len %u)", connId, len);
560
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.
565     {
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);
571     }
572
573 exit:
574     if (err != CHIP_NO_ERROR)
575     {
576         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
577         // TODO: fail connection???
578     }
579 }
580
581 void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt)
582 {
583     CHIP_ERROR err = CHIP_NO_ERROR;
584     bool indicationsEnabled;
585
586     ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", pEvt->hdr.param, 0);
587
588     // Determine if the client is enabling or disabling indications.
589     indicationsEnabled = (pEvt->value != 0);
590
591     // If the client has requested to enabled indications
592     if (indicationsEnabled)
593     {
594         // Set subcription only the first time
595         if (!IsSubscribed(pEvt->hdr.param))
596         {
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);
600             SuccessOrExit(err);
601         }
602     }
603
604     else
605     {
606         // If indications had previously been enabled for this connection, record that they are no longer
607         // enabled.
608         UnsetSubscribed(pEvt->hdr.param);
609     }
610
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.
613     {
614         ChipDeviceEvent event;
615         event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
616         event.CHIPoBLESubscribe.ConId = pEvt->hdr.param;
617         PlatformMgr().PostEvent(&event);
618     }
619
620     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
621
622 exit:
623     if (err != CHIP_NO_ERROR)
624     {
625         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
626         // TODO: fail connection???
627     }
628 }
629
630 /* Process DM Messages */
631 void BLEManagerImpl::HandleDmMsg(qvCHIP_Ble_DmEvt_t * pDmEvt)
632 {
633     switch (pDmEvt->hdr.event)
634     {
635     case QVCHIP_DM_RESET_CMPL_IND: {
636         break;
637     }
638     case QVCHIP_DM_SCAN_START_IND: {
639         break;
640     }
641     case QVCHIP_DM_SCAN_STOP_IND: {
642         break;
643     }
644     case QVCHIP_DM_ADV_START_IND: {
645         if (pDmEvt->hdr.status != QVCHIP_HCI_SUCCESS)
646         {
647             ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_START_IND error: %d", (int) pDmEvt->advSetStart.hdr.status);
648             ExitNow();
649         }
650
651         ClearFlag(sInstance.mFlags, kFlag_AdvertisingRefreshNeeded);
652
653         // Transition to the Advertising state...
654         if (!GetFlag(sInstance.mFlags, kFlag_Advertising))
655         {
656             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
657
658             SetFlag(sInstance.mFlags, kFlag_Advertising, true);
659
660             // Post a CHIPoBLEAdvertisingChange(Started) event.
661             {
662                 ChipDeviceEvent advChange;
663                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
664                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
665                 PlatformMgr().PostEvent(&advChange);
666             }
667         }
668         break;
669     }
670     case QVCHIP_DM_ADV_STOP_IND: {
671         if (pDmEvt->advSetStop.status != QVCHIP_HCI_SUCCESS)
672         {
673             ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_STOP_IND error: %d", (int) pDmEvt->advSetStop.status);
674             ExitNow();
675         }
676
677         ClearFlag(sInstance.mFlags, kFlag_AdvertisingRefreshNeeded);
678
679         // Transition to the not Advertising state...
680         if (GetFlag(sInstance.mFlags, kFlag_Advertising))
681         {
682             ClearFlag(sInstance.mFlags, kFlag_Advertising);
683
684             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
685
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
690
691             // Post a CHIPoBLEAdvertisingChange(Stopped) event.
692             {
693                 ChipDeviceEvent advChange;
694                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
695                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
696                 PlatformMgr().PostEvent(&advChange);
697             }
698         }
699         break;
700     }
701     case QVCHIP_DM_CONN_OPEN_IND: {
702         ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", pDmEvt->connOpen.hdr.param);
703
704         // Allocate a connection state record for the new connection.
705         mNumGAPCons++;
706
707         // Receiving a connection stops the advertising processes.  So force a refresh of the advertising
708         // state.
709         SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
710         PlatformMgr().ScheduleWork(DriveBLEState, 0);
711         break;
712     }
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);
716
717         // Force a refresh of the advertising state.
718         if (mNumGAPCons > 0)
719         {
720             mNumGAPCons--;
721         }
722
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))
726         {
727             ChipDeviceEvent event;
728             event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
729             event.CHIPoBLEConnectionError.ConId = pDmEvt->connClose.hdr.param;
730             switch (pDmEvt->connClose.reason)
731             {
732             case QVCHIP_HCI_ERR_REMOTE_TERMINATED:
733                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
734                 break;
735             case QVCHIP_HCI_ERR_LOCAL_TERMINATED:
736                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
737                 break;
738             default:
739                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
740                 break;
741             }
742             PlatformMgr().PostEvent(&event);
743         }
744
745         SetFlag(mFlags, kFlag_AdvertisingRefreshNeeded);
746         PlatformMgr().ScheduleWork(DriveBLEState, 0);
747         break;
748     }
749     case QVCHIP_DM_CONN_UPDATE_IND: {
750         break;
751     }
752     default: {
753         break;
754     }
755     }
756
757 exit:
758     PlatformMgr().ScheduleWork(DriveBLEState, 0);
759 }
760
761 /* Process ATT Messages */
762 void BLEManagerImpl::HandleAttMsg(qvCHIP_Ble_AttEvt_t * pAttEvt)
763 {
764     switch (pAttEvt->hdr.event)
765     {
766     case QVCHIP_ATT_MTU_UPDATE_IND: {
767         break;
768     }
769     case QVCHIP_ATTS_HANDLE_VALUE_CNF: {
770         ChipDeviceEvent event;
771
772         event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
773         event.CHIPoBLEIndicateConfirm.ConId = pAttEvt->hdr.param;
774         PlatformMgr().PostEvent(&event);
775         break;
776     }
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:
781         break;
782     case QVCHIP_ATTC_READ_RSP:
783         break;
784     case QVCHIP_ATTC_WRITE_RSP:
785     case QVCHIP_ATTC_WRITE_CMD_RSP:
786     case QVCHIP_ATTC_PREPARE_WRITE_RSP:
787         break;
788     case QVCHIP_ATTC_EXECUTE_WRITE_RSP:
789         break;
790     case QVCHIP_ATTC_HANDLE_VALUE_NTF:
791     case QVCHIP_ATTC_HANDLE_VALUE_IND:
792         break;
793     default: {
794         break;
795     }
796     }
797 }
798
799 void BLEManagerImpl::ExternalCbHandler(qvCHIP_Ble_MsgHdr_t * pMsg)
800 {
801     if (pMsg != nullptr)
802     {
803         PlatformMgr().LockChipStack();
804
805         /* Process advertising/scanning and connection-related messages */
806         if (pMsg->event >= QVCHIP_DM_CBACK_START && pMsg->event <= QVCHIP_DM_CBACK_END)
807         {
808             ChipLogProgress(DeviceLayer, "DM event %d: status %d", pMsg->event, pMsg->status);
809             sInstance.HandleDmMsg((qvCHIP_Ble_DmEvt_t *) pMsg);
810         }
811         /* Process attribute-related messages */
812         else if (pMsg->event >= QVCHIP_ATT_CBACK_START && pMsg->event <= QVCHIP_ATT_CBACK_END)
813         {
814             ChipLogProgress(DeviceLayer, "ATT event %d: status %d", pMsg->event, pMsg->status);
815             sInstance.HandleAttMsg((qvCHIP_Ble_AttEvt_t *) pMsg);
816         }
817         else
818         {
819             ChipLogProgress(DeviceLayer, "Unknown event %d", pMsg->event);
820         }
821
822         PlatformMgr().UnlockChipStack();
823     }
824 }
825
826 CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
827 {
828     uint16_t freeIndex = kMaxConnections;
829
830     for (uint16_t i = 0; i < kMaxConnections; i++)
831     {
832         if (mSubscribedConIds[i] == conId)
833         {
834             return CHIP_NO_ERROR;
835         }
836         else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex)
837         {
838             freeIndex = i;
839         }
840     }
841
842     if (freeIndex < kMaxConnections)
843     {
844         mSubscribedConIds[freeIndex] = conId;
845         return CHIP_NO_ERROR;
846     }
847     else
848     {
849         return CHIP_ERROR_NO_MEMORY;
850     }
851 }
852
853 bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
854 {
855     for (uint16_t i = 0; i < kMaxConnections; i++)
856     {
857         if (mSubscribedConIds[i] == conId)
858         {
859             mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
860             return true;
861         }
862     }
863     return false;
864 }
865
866 bool BLEManagerImpl::IsSubscribed(uint16_t conId)
867 {
868     if (conId != BLE_CONNECTION_UNINITIALIZED)
869     {
870         for (uint16_t i = 0; i < kMaxConnections; i++)
871         {
872             if (mSubscribedConIds[i] == conId)
873             {
874                 return true;
875             }
876         }
877     }
878     return false;
879 }
880
881 void BLEManagerImpl::_handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event)
882 {
883     sInstance.HandleTXCharCCCDWrite(event);
884 }
885
886 } // namespace Internal
887 } // namespace DeviceLayer
888 } // namespace chip
889
890 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE