diff --git a/Library/Classes/Implementation/DFUServiceDelegate.swift b/Library/Classes/Implementation/DFUServiceDelegate.swift index 3132987e..544ba0da 100644 --- a/Library/Classes/Implementation/DFUServiceDelegate.swift +++ b/Library/Classes/Implementation/DFUServiceDelegate.swift @@ -244,6 +244,8 @@ internal enum DFURemoteError : Int { @objc public enum DFUState : Int { /// Service is connecting to the DFU target. case connecting + /// Service is connected to the DFU target. + case connected /// DFU Service is initializing DFU operation. case starting /// DFU Service is switching the device to DFU mode. @@ -254,6 +256,8 @@ internal enum DFURemoteError : Int { case validating /// The iDevice is disconnecting or waiting for disconnection. case disconnecting + /// The iDevice is disconnected. + case disconnected /// DFU operation is completed and successful. case completed /// DFU operation was aborted. @@ -265,11 +269,13 @@ extension DFUState : CustomStringConvertible { public var description: String { switch self { case .connecting: return "Connecting" + case .connected: return "Connected" case .starting: return "Starting" case .enablingDfuMode: return "Enabling DFU Mode" case .uploading: return "Uploading" case .validating: return "Validating" // This state occurs only in Legacy DFU. case .disconnecting: return "Disconnecting" + case .disconnected: return "Disconnected" case .completed: return "Completed" case .aborted: return "Aborted" } diff --git a/Library/Classes/Implementation/GenericDFU/DFUExecutor.swift b/Library/Classes/Implementation/GenericDFU/DFUExecutor.swift index 3c3be04f..0fc42537 100644 --- a/Library/Classes/Implementation/GenericDFU/DFUExecutor.swift +++ b/Library/Classes/Implementation/GenericDFU/DFUExecutor.swift @@ -71,8 +71,18 @@ extension BaseDFUExecutor { } // MARK: - BasePeripheralDelegate API - + + func peripheralDidConnect() { + delegate { + $0.dfuStateDidChange(to: .connected) + } + } + func peripheralDidFailToConnect() { + delegate { + $0.dfuStateDidChange(to: .disconnected) + } + delegate { $0.dfuError(.failedToConnect, didOccurWithMessage: "Device failed to connect") } @@ -90,6 +100,11 @@ extension BaseDFUExecutor { peripheral.reconnect() return } + + delegate { + $0.dfuStateDidChange(to: .disconnected) + } + // Check if there was an error that needs to be reported now. delegate { $0.dfuError(error.error, didOccurWithMessage: error.message) @@ -99,6 +114,10 @@ extension BaseDFUExecutor { } func peripheralDidDisconnect(withError error: Error) { + delegate { + $0.dfuStateDidChange(to: .disconnected) + } + delegate { $0.dfuError(.deviceDisconnected, didOccurWithMessage: "\(error.localizedDescription) (code: \((error as NSError).code))") @@ -111,11 +130,16 @@ extension BaseDFUExecutor { delegate { $0.dfuStateDidChange(to: .aborted) } + // Release the cyclic reference. peripheral.destroy() } func error(_ error: DFUError, didOccurWithMessage message: String) { + delegate { + $0.dfuStateDidChange(to: .disconnected) + } + if error == .bluetoothDisabled { delegate { $0.dfuError(.bluetoothDisabled, didOccurWithMessage: message) diff --git a/Library/Classes/Implementation/GenericDFU/DFUPeripheral.swift b/Library/Classes/Implementation/GenericDFU/DFUPeripheral.swift index b5edabfd..9a3a0db2 100644 --- a/Library/Classes/Implementation/GenericDFU/DFUPeripheral.swift +++ b/Library/Classes/Implementation/GenericDFU/DFUPeripheral.swift @@ -159,22 +159,25 @@ internal class BaseDFUPeripheral : NSObject, BaseDF self.peripheral = peripheral switch peripheral.state { - case .connected: - let name = peripheral.name ?? "Unknown device" - logger.i("Connected to \(name)") - - if let dfuService = findDfuService(in: peripheral.services) { - // A DFU service was found, congratulations! - logger.i("Services discovered") - peripheralDidDiscoverDfuService(dfuService) - } else { - // DFU service has not been found, but it doesn't matter it's not - // there. Perhaps the user's application didn't discover it. - // Let's discover DFU services. - discoverServices() - } - default: - connect() + case .connected: + + let name = peripheral.name ?? "Unknown device" + logger.i("Connected to \(name)") + + delegate?.peripheralDidConnect() + + if let dfuService = findDfuService(in: peripheral.services) { + // A DFU service was found, congratulations! + logger.i("Services discovered") + peripheralDidDiscoverDfuService(dfuService) + } else { + // DFU service has not been found, but it doesn't matter it's not + // there. Perhaps the user's application didn't discover it. + // Let's discover DFU services. + discoverServices() + } + default: + connect() } } @@ -225,7 +228,7 @@ internal class BaseDFUPeripheral : NSObject, BaseDF func abort() -> Bool { aborted = true - if peripheral?.state == .connecting { + if peripheral?.state == .connecting || peripheral?.state == .connected { disconnect() } return true @@ -277,7 +280,9 @@ internal class BaseDFUPeripheral : NSObject, BaseDF resetDevice() return } - + + delegate?.peripheralDidConnect() + discoverServices() } diff --git a/Library/Classes/Implementation/GenericDFU/DFUPeripheralDelegate.swift b/Library/Classes/Implementation/GenericDFU/DFUPeripheralDelegate.swift index 0841bd58..9f2f14d5 100644 --- a/Library/Classes/Implementation/GenericDFU/DFUPeripheralDelegate.swift +++ b/Library/Classes/Implementation/GenericDFU/DFUPeripheralDelegate.swift @@ -29,7 +29,12 @@ */ internal protocol BasePeripheralDelegate: AnyObject { - + + /** + Method called when the iDevice successfully connected to the given peripheral. + */ + func peripheralDidConnect() + /** Method called when the iDevice failed to connect to the given peripheral. The DFU operation will be aborter as nothing can be done.