Fix for x86_64 build fail
[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.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
72     mFlags.Set(Flags::kFastAdvertisingEnabled, true);
73     mNumGAPCons = 0;
74     for (int i = 0; i < kMaxConnections; i++)
75     {
76         mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
77     }
78
79     // Initialize the CHIP BleLayer.
80     err = BleLayer::Init(this, this, &SystemLayer);
81     SuccessOrExit(err);
82
83     appCbacks.stackCback    = ExternalCbHandler;
84     appCbacks.chrReadCback  = HandleTXCharRead;
85     appCbacks.chrWriteCback = HandleRXCharWrite;
86     appCbacks.cccCback      = _handleTXCharCCCDWrite;
87     qvCHIP_BleInit(&appCbacks);
88
89     PlatformMgr().ScheduleWork(DriveBLEState, 0);
90 exit:
91     ChipLogProgress(DeviceLayer, "BLEManagerImpl::Init() complete");
92
93     return err;
94 }
95
96 CHIP_ERROR BLEManagerImpl::_SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val)
97 {
98     CHIP_ERROR err = CHIP_NO_ERROR;
99
100     VerifyOrExit(val != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
101     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
102
103     if (val != mServiceMode)
104     {
105         mServiceMode = val;
106         PlatformMgr().ScheduleWork(DriveBLEState, 0);
107     }
108
109 exit:
110     return err;
111 }
112
113 CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val)
114 {
115     CHIP_ERROR err = CHIP_NO_ERROR;
116
117     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
118
119     if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
120     {
121         mFlags.Set(Flags::kAdvertisingEnabled, val);
122         PlatformMgr().ScheduleWork(DriveBLEState, 0);
123     }
124
125 exit:
126     return err;
127 }
128
129 CHIP_ERROR BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
130 {
131     switch (mode)
132     {
133     case BLEAdvertisingMode::kFastAdvertising:
134         mFlags.Set(Flags::kFastAdvertisingEnabled, true);
135         break;
136     case BLEAdvertisingMode::kSlowAdvertising:
137         mFlags.Set(Flags::kFastAdvertisingEnabled, false);
138         break;
139     default:
140         return CHIP_ERROR_INVALID_ARGUMENT;
141     }
142     mFlags.Set(Flags::kAdvertisingRefreshNeeded);
143     PlatformMgr().ScheduleWork(DriveBLEState, 0);
144     return CHIP_NO_ERROR;
145 }
146
147 CHIP_ERROR BLEManagerImpl::_GetDeviceName(char * buf, size_t bufSize)
148 {
149     CHIP_ERROR err;
150
151     err = MapBLEError(qvCHIP_BleGetDeviceName(buf, bufSize));
152
153     return err;
154 }
155
156 CHIP_ERROR BLEManagerImpl::_SetDeviceName(const char * devName)
157 {
158     CHIP_ERROR err = CHIP_NO_ERROR;
159
160     VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
161
162     if (devName != nullptr && devName[0] != 0)
163     {
164         err = MapBLEError(qvCHIP_BleSetDeviceName(devName));
165     }
166
167 exit:
168     return err;
169 }
170
171 void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
172 {
173     switch (event->Type)
174     {
175     // Platform specific events
176     case DeviceEventType::kCHIPoBLESubscribe: {
177         ChipDeviceEvent connEstEvent;
178
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);
183     }
184     break;
185
186     case DeviceEventType::kCHIPoBLEUnsubscribe: {
187         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
188         HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
189     }
190     break;
191
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));
196     }
197     break;
198
199     case DeviceEventType::kCHIPoBLEConnectionError: {
200         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
201         HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
202     }
203     break;
204     // Generic CHIP events
205     case DeviceEventType::kFabricMembershipChange:
206     case DeviceEventType::kServiceProvisioningChange:
207     case DeviceEventType::kAccountPairingChange:
208
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())
214         {
215             mFlags.Clear(Flags::kAdvertisingEnabled);
216             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
217         }
218 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
219
220         // Force the advertising state to be refreshed to reflect new provisioning state.
221         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
222
223         DriveBLEState();
224
225         break;
226
227     case DeviceEventType::kCHIPoBLEIndicateConfirm: {
228         ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
229         HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &chipUUID_CHIPoBLEChar_TX);
230     }
231     break;
232
233     default:
234         ChipLogProgress(DeviceLayer, "_OnPlatformEvent default:  event->Type = %d", event->Type);
235         break;
236     }
237 }
238
239 bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
240 {
241     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
242     return false;
243 }
244
245 bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
246 {
247     ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
248     return false;
249 }
250
251 bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
252 {
253     CHIP_ERROR err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
254
255     ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
256
257     err = MapBLEError(qvCHIP_BleCloseConnection(conId));
258     if (err != CHIP_NO_ERROR)
259     {
260         ChipLogError(DeviceLayer, "qvCHIP_BleCloseConnection() failed: %s", ErrorStr(err));
261     }
262
263     return (err == CHIP_NO_ERROR);
264 }
265
266 uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
267 {
268     uint16_t retVal = 0;
269     CHIP_ERROR err  = MapBLEError(qvCHIP_BleGetMTU(conId, &retVal));
270     if (err != CHIP_NO_ERROR)
271     {
272         ChipLogError(DeviceLayer, "qvCHIP_BleGetMTU() failed: %s", ErrorStr(err));
273     }
274
275     return retVal;
276 }
277
278 bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
279                                     PacketBufferHandle data)
280 {
281     CHIP_ERROR err = CHIP_NO_ERROR;
282     bool isRxHandle;
283     uint16_t cId;
284     uint16_t dataLen = data->DataLength();
285
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);
288
289     isRxHandle = UUIDsMatch(&chipUUID_CHIPoBLEChar_TX, charId);
290     cId        = qvCHIP_BleGetHandle(isRxHandle);
291
292     qvCHIP_BleSendIndication(conId, cId, dataLen, data->Start());
293
294 exit:
295     if (err != CHIP_NO_ERROR)
296     {
297         ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
298         return false;
299     }
300     return true;
301 }
302
303 bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
304                                       PacketBufferHandle pBuf)
305 {
306     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
307     return false;
308 }
309
310 bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
311                                      PacketBufferHandle pBuf)
312 {
313     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
314     return false;
315 }
316
317 bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
318                                       const ChipBleUUID * svcId, const ChipBleUUID * charId)
319 {
320     ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
321     return false;
322 }
323
324 void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
325 {
326     // Nothing to do
327 }
328
329 CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr) const
330 {
331     CHIP_ERROR err;
332
333     switch (bleErr)
334     {
335     case QV_STATUS_NO_ERROR: {
336         err = CHIP_NO_ERROR;
337         break;
338     }
339     case QV_STATUS_BUFFER_TOO_SMALL: {
340         err = CHIP_ERROR_BUFFER_TOO_SMALL;
341         break;
342     }
343     case QV_STATUS_INVALID_ARGUMENT: {
344         err = CHIP_ERROR_INVALID_ARGUMENT;
345         break;
346     }
347     default: {
348         err = CHIP_ERROR_INCORRECT_STATE;
349     }
350     }
351     return err;
352 }
353
354 void BLEManagerImpl::DriveBLEState(void)
355 {
356     CHIP_ERROR err = CHIP_NO_ERROR;
357
358     // Perform any initialization actions that must occur after the CHIP task is running.
359     if (!mFlags.Has(Flags::kAsyncInitCompleted))
360     {
361         mFlags.Set(Flags::kAsyncInitCompleted);
362
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())
367         {
368             mFlags.Clear(Flags::kAdvertisingEnabled);
369             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising disabled because device is fully provisioned");
370         }
371 #endif // CHIP_DEVICE_CONFIG_CHIPOBLE_DISABLE_ADVERTISING_WHEN_PROVISIONED
372     }
373
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)
380 #endif
381     )
382     {
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))
386         {
387             mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
388             err = StartAdvertising();
389             SuccessOrExit(err);
390         }
391     }
392
393     // Otherwise, stop advertising if currently active.
394     else
395     {
396         err = StopAdvertising();
397         SuccessOrExit(err);
398     }
399
400 exit:
401     if (err != CHIP_NO_ERROR)
402     {
403         ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
404         mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
405     }
406 }
407
408 CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
409 {
410     ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
411     CHIP_ERROR err;
412     uint8_t index               = 0;
413     uint8_t mDeviceNameLength   = 0;
414     uint8_t mDeviceIdInfoLength = 0;
415
416     memset(mAdvDataBuf, 0, kMaxAdvertisementDataSetSize);
417     memset(mScanRespDataBuf, 0, kMaxAdvertisementDataSetSize);
418
419     err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
420     SuccessOrExit(err);
421
422     if (!mFlags.Has(Flags::kDeviceNameSet))
423     {
424         snprintf(mDeviceName, sizeof(mDeviceName), "%s%04" PRIX32, CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, (uint32_t) 0);
425
426         mDeviceName[kMaxDeviceNameLength] = 0;
427         err                               = MapBLEError(qvCHIP_BleSetDeviceName(mDeviceName));
428         SuccessOrExit(err);
429     }
430
431     mDeviceNameLength   = static_cast<uint8_t>(strlen(mDeviceName));
432     mDeviceIdInfoLength = sizeof(mDeviceIdInfo);
433
434     // Check sizes
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");
438
439     // Fill in advertising data
440     index                = 0;
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
444
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);
451
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);
456
457     qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_ADV, index, mAdvDataBuf);
458
459     // Fill in scan response data
460     index                     = 0;
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;
465
466     qvCHIP_BleSetAdvData(QV_ADV_DATA_LOC_SCAN, index, mScanRespDataBuf);
467
468 exit:
469     return err;
470 }
471
472 CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
473 {
474     CHIP_ERROR err;
475     uint16_t intervalMin;
476     uint16_t intervalMax;
477     ChipLogProgress(DeviceLayer, "CHIPoBLE start advertising");
478
479     err = ConfigureAdvertisingData();
480     SuccessOrExit(err);
481
482     mFlags.Set(Flags::kAdvertising);
483
484     if ((mNumGAPCons == 0 && !ConfigurationMgr().IsPairedToAccount()) || mFlags.Has(Flags::kFastAdvertisingEnabled))
485     {
486         intervalMin = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
487         intervalMax = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
488     }
489     else
490     {
491         intervalMin = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
492         intervalMax = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
493     }
494
495     qvCHIP_BleSetAdvInterval(intervalMin, intervalMax);
496
497     err = MapBLEError(qvCHIP_BleStartAdvertising());
498     SuccessOrExit(err);
499
500 exit:
501     return err;
502 }
503
504 CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
505 {
506     CHIP_ERROR err;
507
508     err = MapBLEError(qvCHIP_BleStopAdvertising());
509     SuccessOrExit(err);
510
511     // Transition to the not Advertising state...
512     if (mFlags.Has(Flags::kAdvertising))
513     {
514         mFlags.Clear(Flags::kAdvertising);
515         mFlags.Set(Flags::kFastAdvertisingEnabled, true);
516
517         ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
518
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
523
524         // Post a CHIPoBLEAdvertisingChange(Stopped) event.
525         {
526             ChipDeviceEvent advChange;
527             advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
528             advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
529             PlatformMgr().PostEvent(&advChange);
530         }
531     }
532
533 exit:
534     return err;
535 }
536
537 uint16_t BLEManagerImpl::_NumConnections(void)
538 {
539     uint16_t numCons = 0;
540     for (uint16_t i = 0; i < kMaxConnections; i++)
541     {
542         if (mSubscribedConIds[i] != BLE_CONNECTION_UNINITIALIZED)
543         {
544             numCons++;
545         }
546     }
547     return numCons;
548 }
549
550 void BLEManagerImpl::DriveBLEState(intptr_t arg)
551 {
552     sInstance.DriveBLEState();
553 }
554
555 void BLEManagerImpl::HandleTXCharRead(uint16_t connId, uint16_t handle, uint8_t operation, uint16_t offset,
556                                       qvCHIP_Ble_Attr_t * pAttr)
557 {
558     uint8_t rsp = 0;
559
560     ChipLogProgress(DeviceLayer, "Read request received for CHIPoBLE Client RX characteristic (con %u)", connId);
561
562     // Send a zero-length response.
563     qvCHIP_BleWriteAttr(connId, handle, 0, &rsp);
564 }
565
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)
568 {
569     CHIP_ERROR err = CHIP_NO_ERROR;
570
571     ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE Client TX characteristic (con %u, len %u)", connId, len);
572
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.
577     {
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);
583     }
584
585 exit:
586     if (err != CHIP_NO_ERROR)
587     {
588         ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
589         // TODO: fail connection???
590     }
591 }
592
593 void BLEManagerImpl::HandleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * pEvt)
594 {
595     CHIP_ERROR err = CHIP_NO_ERROR;
596     bool indicationsEnabled;
597
598     ChipLogProgress(DeviceLayer, "Write request received for CHIPoBLE TX characteristic CCCD (con %u, len %u)", pEvt->hdr.param, 0);
599
600     // Determine if the client is enabling or disabling indications.
601     indicationsEnabled = (pEvt->value != 0);
602
603     // If the client has requested to enabled indications
604     if (indicationsEnabled)
605     {
606         // Set subcription only the first time
607         if (!IsSubscribed(pEvt->hdr.param))
608         {
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);
612             SuccessOrExit(err);
613         }
614     }
615
616     else
617     {
618         // If indications had previously been enabled for this connection, record that they are no longer
619         // enabled.
620         UnsetSubscribed(pEvt->hdr.param);
621     }
622
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.
625     {
626         ChipDeviceEvent event;
627         event.Type = (indicationsEnabled) ? DeviceEventType::kCHIPoBLESubscribe : DeviceEventType::kCHIPoBLEUnsubscribe;
628         event.CHIPoBLESubscribe.ConId = pEvt->hdr.param;
629         PlatformMgr().PostEvent(&event);
630     }
631
632     ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", indicationsEnabled ? "subscribe" : "unsubscribe");
633
634 exit:
635     if (err != CHIP_NO_ERROR)
636     {
637         ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
638         // TODO: fail connection???
639     }
640 }
641
642 /* Process DM Messages */
643 void BLEManagerImpl::HandleDmMsg(qvCHIP_Ble_DmEvt_t * pDmEvt)
644 {
645     switch (pDmEvt->hdr.event)
646     {
647     case QVCHIP_DM_RESET_CMPL_IND: {
648         break;
649     }
650     case QVCHIP_DM_SCAN_START_IND: {
651         break;
652     }
653     case QVCHIP_DM_SCAN_STOP_IND: {
654         break;
655     }
656     case QVCHIP_DM_ADV_START_IND: {
657         if (pDmEvt->hdr.status != QVCHIP_HCI_SUCCESS)
658         {
659             ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_START_IND error: %d", (int) pDmEvt->advSetStart.hdr.status);
660             ExitNow();
661         }
662
663         sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
664
665         // Transition to the Advertising state...
666         if (!sInstance.mFlags.Has(Flags::kAdvertising))
667         {
668             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising started");
669
670             sInstance.mFlags.Set(Flags::kAdvertising);
671
672             // Post a CHIPoBLEAdvertisingChange(Started) event.
673             {
674                 ChipDeviceEvent advChange;
675                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
676                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
677                 PlatformMgr().PostEvent(&advChange);
678             }
679         }
680         break;
681     }
682     case QVCHIP_DM_ADV_STOP_IND: {
683         if (pDmEvt->advSetStop.status != QVCHIP_HCI_SUCCESS)
684         {
685             ChipLogError(DeviceLayer, "QVCHIP_DM_ADV_STOP_IND error: %d", (int) pDmEvt->advSetStop.status);
686             ExitNow();
687         }
688
689         sInstance.mFlags.Clear(Flags::kAdvertisingRefreshNeeded);
690
691         // Transition to the not Advertising state...
692         if (sInstance.mFlags.Has(Flags::kAdvertising))
693         {
694             sInstance.mFlags.Clear(Flags::kAdvertising);
695
696             ChipLogProgress(DeviceLayer, "CHIPoBLE advertising stopped");
697
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
702
703             // Post a CHIPoBLEAdvertisingChange(Stopped) event.
704             {
705                 ChipDeviceEvent advChange;
706                 advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
707                 advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
708                 PlatformMgr().PostEvent(&advChange);
709             }
710         }
711         break;
712     }
713     case QVCHIP_DM_CONN_OPEN_IND: {
714         ChipLogProgress(DeviceLayer, "BLE GATT connection established (con %u)", pDmEvt->connOpen.hdr.param);
715
716         // Allocate a connection state record for the new connection.
717         mNumGAPCons++;
718
719         // Receiving a connection stops the advertising processes.  So force a refresh of the advertising
720         // state.
721         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
722         PlatformMgr().ScheduleWork(DriveBLEState, 0);
723         break;
724     }
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);
728
729         // Force a refresh of the advertising state.
730         if (mNumGAPCons > 0)
731         {
732             mNumGAPCons--;
733         }
734
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))
738         {
739             ChipDeviceEvent event;
740             event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
741             event.CHIPoBLEConnectionError.ConId = pDmEvt->connClose.hdr.param;
742             switch (pDmEvt->connClose.reason)
743             {
744             case QVCHIP_HCI_ERR_REMOTE_TERMINATED:
745                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
746                 break;
747             case QVCHIP_HCI_ERR_LOCAL_TERMINATED:
748                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
749                 break;
750             default:
751                 event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
752                 break;
753             }
754             PlatformMgr().PostEvent(&event);
755         }
756
757         mFlags.Set(Flags::kAdvertisingRefreshNeeded);
758         PlatformMgr().ScheduleWork(DriveBLEState, 0);
759         break;
760     }
761     case QVCHIP_DM_CONN_UPDATE_IND: {
762         break;
763     }
764     default: {
765         break;
766     }
767     }
768
769 exit:
770     PlatformMgr().ScheduleWork(DriveBLEState, 0);
771 }
772
773 /* Process ATT Messages */
774 void BLEManagerImpl::HandleAttMsg(qvCHIP_Ble_AttEvt_t * pAttEvt)
775 {
776     switch (pAttEvt->hdr.event)
777     {
778     case QVCHIP_ATT_MTU_UPDATE_IND: {
779         break;
780     }
781     case QVCHIP_ATTS_HANDLE_VALUE_CNF: {
782         ChipDeviceEvent event;
783
784         event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
785         event.CHIPoBLEIndicateConfirm.ConId = pAttEvt->hdr.param;
786         PlatformMgr().PostEvent(&event);
787         break;
788     }
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:
793         break;
794     case QVCHIP_ATTC_READ_RSP:
795         break;
796     case QVCHIP_ATTC_WRITE_RSP:
797     case QVCHIP_ATTC_WRITE_CMD_RSP:
798     case QVCHIP_ATTC_PREPARE_WRITE_RSP:
799         break;
800     case QVCHIP_ATTC_EXECUTE_WRITE_RSP:
801         break;
802     case QVCHIP_ATTC_HANDLE_VALUE_NTF:
803     case QVCHIP_ATTC_HANDLE_VALUE_IND:
804         break;
805     default: {
806         break;
807     }
808     }
809 }
810
811 void BLEManagerImpl::ExternalCbHandler(qvCHIP_Ble_MsgHdr_t * pMsg)
812 {
813     if (pMsg != nullptr)
814     {
815         PlatformMgr().LockChipStack();
816
817         /* Process advertising/scanning and connection-related messages */
818         if (pMsg->event >= QVCHIP_DM_CBACK_START && pMsg->event <= QVCHIP_DM_CBACK_END)
819         {
820             ChipLogProgress(DeviceLayer, "DM event %d: status %d", pMsg->event, pMsg->status);
821             sInstance.HandleDmMsg((qvCHIP_Ble_DmEvt_t *) pMsg);
822         }
823         /* Process attribute-related messages */
824         else if (pMsg->event >= QVCHIP_ATT_CBACK_START && pMsg->event <= QVCHIP_ATT_CBACK_END)
825         {
826             ChipLogProgress(DeviceLayer, "ATT event %d: status %d", pMsg->event, pMsg->status);
827             sInstance.HandleAttMsg((qvCHIP_Ble_AttEvt_t *) pMsg);
828         }
829         else
830         {
831             ChipLogProgress(DeviceLayer, "Unknown event %d", pMsg->event);
832         }
833
834         PlatformMgr().UnlockChipStack();
835     }
836 }
837
838 CHIP_ERROR BLEManagerImpl::SetSubscribed(uint16_t conId)
839 {
840     uint16_t freeIndex = kMaxConnections;
841
842     for (uint16_t i = 0; i < kMaxConnections; i++)
843     {
844         if (mSubscribedConIds[i] == conId)
845         {
846             return CHIP_NO_ERROR;
847         }
848         else if (mSubscribedConIds[i] == BLE_CONNECTION_UNINITIALIZED && i < freeIndex)
849         {
850             freeIndex = i;
851         }
852     }
853
854     if (freeIndex < kMaxConnections)
855     {
856         mSubscribedConIds[freeIndex] = conId;
857         return CHIP_NO_ERROR;
858     }
859     else
860     {
861         return CHIP_ERROR_NO_MEMORY;
862     }
863 }
864
865 bool BLEManagerImpl::UnsetSubscribed(uint16_t conId)
866 {
867     for (uint16_t i = 0; i < kMaxConnections; i++)
868     {
869         if (mSubscribedConIds[i] == conId)
870         {
871             mSubscribedConIds[i] = BLE_CONNECTION_UNINITIALIZED;
872             return true;
873         }
874     }
875     return false;
876 }
877
878 bool BLEManagerImpl::IsSubscribed(uint16_t conId)
879 {
880     if (conId != BLE_CONNECTION_UNINITIALIZED)
881     {
882         for (uint16_t i = 0; i < kMaxConnections; i++)
883         {
884             if (mSubscribedConIds[i] == conId)
885             {
886                 return true;
887             }
888         }
889     }
890     return false;
891 }
892
893 void BLEManagerImpl::_handleTXCharCCCDWrite(qvCHIP_Ble_AttsCccEvt_t * event)
894 {
895     sInstance.HandleTXCharCCCDWrite(event);
896 }
897
898 } // namespace Internal
899 } // namespace DeviceLayer
900 } // namespace chip
901
902 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE