diff --git a/src/platform/Darwin/BleConnectionDelegateImpl.mm b/src/platform/Darwin/BleConnectionDelegateImpl.mm index 6d56573959b6b9..8baed2da9be929 100644 --- a/src/platform/Darwin/BleConnectionDelegateImpl.mm +++ b/src/platform/Darwin/BleConnectionDelegateImpl.mm @@ -226,16 +226,10 @@ - (id)initWithQueue:(dispatch_queue_t)queue self.shortServiceUUID = [UUIDHelper GetShortestServiceUUID:&chip::Ble::CHIP_BLE_SVC_ID]; _chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue(); _workQueue = queue; - _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); _centralManager = [CBCentralManager alloc]; _found = false; _cachedPeripherals = [[NSMutableDictionary alloc] init]; _currentMode = kUndefined; - - dispatch_source_set_event_handler(_timer, ^{ - [self stop]; - [self dispatchConnectionError:BLE_ERROR_APP_CLOSED_CONNECTION]; - }); } return self; @@ -247,7 +241,9 @@ - (id)initWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate queue:( if (self) { _scannerDelegate = delegate; _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning; - [self resetTimer]; + if (_currentMode == kScanningWithoutDelegate) { + [self setupTimer:kScanningWithoutDelegateTimeoutInSeconds]; + } } return self; @@ -259,7 +255,7 @@ - (id)initWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminato if (self) { _deviceDiscriminator = deviceDiscriminator; _currentMode = kConnecting; - [self resetTimer]; + [self setupTimer:kScanningWithDiscriminatorTimeoutInSeconds]; } return self; @@ -280,20 +276,26 @@ - (BOOL)isConnecting return _currentMode == kConnecting; } -- (void)resetTimer +- (void)setupTimer:(uint64_t)timeout { - if ([self isConnecting]) { - auto timeout = static_cast(kScanningWithDiscriminatorTimeoutInSeconds * NSEC_PER_SEC); - dispatch_source_set_timer(_timer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC); - } else if ([self isScanningWithoutDelegate]) { - auto timeout = static_cast(kScanningWithoutDelegateTimeoutInSeconds * NSEC_PER_SEC); - dispatch_source_set_timer(_timer, dispatch_walltime(nullptr, timeout), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC); - } else if ([self isScanning]) { - dispatch_source_cancel(_timer); - } else { - // It should not happens. + [self clearTimer]; + + _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _workQueue); + dispatch_source_set_event_handler(_timer, ^{ [self stop]; - [self dispatchConnectionError:CHIP_ERROR_INCORRECT_STATE]; + [self dispatchConnectionError:BLE_ERROR_APP_CLOSED_CONNECTION]; + }); + + auto value = static_cast(timeout * NSEC_PER_SEC); + dispatch_source_set_timer(_timer, dispatch_walltime(nullptr, value), DISPATCH_TIME_FOREVER, 5 * NSEC_PER_SEC); + dispatch_resume(_timer); +} + +- (void)clearTimer +{ + if (_timer) { + dispatch_source_cancel(_timer); + _timer = nil; } } @@ -544,8 +546,6 @@ - (void)peripheral:(CBPeripheral *)peripheral - (void)start { - dispatch_resume(_timer); - // If a peripheral has already been found, try to connect to it once BLE starts, // otherwise start scanning to find the peripheral to connect to. if (_peripheral != nil) { @@ -557,12 +557,12 @@ - (void)start - (void)stop { + _scannerDelegate = nil; + _found = false; [self stopScanning]; [self removePeripheralsFromCache]; - _cachedPeripherals = nil; - _scannerDelegate = nil; - if (!_centralManager || !_peripheral) { + if (!_centralManager && !_peripheral) { return; } @@ -573,12 +573,15 @@ - (void)stop // able to reach those. // This is why closing connections happens as 2 async steps. dispatch_async(_chipWorkQueue, ^{ - _mBleLayer->CloseAllBleConnections(); + if (_peripheral) { + _mBleLayer->CloseAllBleConnections(); + } dispatch_async(_workQueue, ^{ _centralManager.delegate = nil; _centralManager = nil; _peripheral = nil; + chip::DeviceLayer::Internal::ble = nil; }); }); } @@ -598,7 +601,8 @@ - (void)stopScanning if (!_centralManager) { return; } - dispatch_source_cancel(_timer); + + [self clearTimer]; [_centralManager stopScan]; } @@ -618,6 +622,8 @@ - (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate _currentMode = (delegate == nullptr) ? kScanningWithoutDelegate : kScanning; if (_currentMode == kScanning) { + [self clearTimer]; + for (CBPeripheral * cachedPeripheral in _cachedPeripherals) { NSData * serviceData = _cachedPeripherals[cachedPeripheral][@"data"]; dispatch_async(_chipWorkQueue, ^{ @@ -626,9 +632,9 @@ - (void)updateWithDelegate:(chip::DeviceLayer::BleScannerDelegate *)delegate _scannerDelegate->OnBleScanAdd((__bridge void *) cachedPeripheral, info); }); } + } else { + [self setupTimer:kScanningWithoutDelegateTimeoutInSeconds]; } - - [self resetTimer]; } - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscriminator @@ -656,7 +662,7 @@ - (void)updateWithDiscriminator:(const chip::SetupDiscriminator &)deviceDiscrimi [self connect:peripheral]; [self stopScanning]; } else { - [self resetTimer]; + [self setupTimer:kScanningWithDiscriminatorTimeoutInSeconds]; } }