@@ -52,6 +52,7 @@ var pairedDeviceIdentifiers: Set<String> {
52
52
}
53
53
54
54
class BLEConnectionContext {
55
+ let identifier = UUID ( )
55
56
let semaphore = DispatchSemaphore ( value: 0 )
56
57
var readBuffer = Data ( )
57
58
var readBufferLock = NSLock ( )
@@ -294,9 +295,6 @@ class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CB
294
295
}
295
296
296
297
func handleDisconnect( ) {
297
- currentContextLock. lock ( )
298
- currentContext = nil
299
- currentContextLock. unlock ( )
300
298
connectedPeripheral = nil
301
299
pReader = nil
302
300
pWriter = nil
@@ -309,6 +307,12 @@ class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CB
309
307
// Otherwise there would be up to a second of delay (the backend device manager scan interval).
310
308
MobileserverUsbUpdate ( )
311
309
310
+ // Unblock a pending readBlocking() call if there is one.
311
+ currentContextLock. lock ( )
312
+ currentContext? . semaphore. signal ( )
313
+ currentContext = nil
314
+ currentContextLock. unlock ( )
315
+
312
316
restartScan ( )
313
317
}
314
318
@@ -318,25 +322,42 @@ class BluetoothManager: NSObject, ObservableObject, CBCentralManagerDelegate, CB
318
322
handleDisconnect ( )
319
323
}
320
324
321
- func readBlocking( length: Int ) -> Data ? {
325
+ struct ReadError : Error {
326
+ let message : String
327
+ }
328
+
329
+ func readBlocking( length: Int ) throws -> Data {
322
330
if !isConnected( ) {
323
- return nil
331
+ throw ReadError ( message : " not connected " )
324
332
}
325
333
print ( " BLE: wants to read \( length) " )
326
334
327
335
currentContextLock. lock ( )
328
336
guard let ctx = currentContext else {
329
337
currentContextLock. unlock ( )
330
- return nil
338
+ throw ReadError ( message : " no connection context " )
331
339
}
332
340
currentContextLock. unlock ( )
341
+
342
+ let currentID = ctx. identifier;
333
343
334
344
var data = Data ( )
335
345
336
346
// Loop until we've read the required amount of data
337
347
while data. count < length {
338
- // Block until BLE reader callback notifies us
348
+ // Block until BLE reader callback notifies us or the peripheral is disconnected.
339
349
ctx. semaphore. wait ( )
350
+
351
+ if !isConnected( ) {
352
+ throw ReadError ( message: " the peripheral has disconnected while reading " )
353
+ }
354
+ currentContextLock. lock ( )
355
+ let exit = currentContext? . identifier != currentID
356
+ currentContextLock. unlock ( )
357
+ if exit {
358
+ throw ReadError ( message: " the peripheral has disconnected while reading " )
359
+ }
360
+
340
361
ctx. readBufferLock. lock ( )
341
362
data. append ( ctx. readBuffer. prefix ( 64 ) )
342
363
ctx. readBuffer = ctx. readBuffer. advanced ( by: 64 )
@@ -485,7 +506,7 @@ class BluetoothReadWriteCloser: NSObject, MobileserverGoReadWriteCloserInterface
485
506
}
486
507
487
508
func read( _ n: Int ) throws -> Data {
488
- return bluetoothManager. readBlocking ( length: n) !
509
+ try bluetoothManager. readBlocking ( length: n)
489
510
}
490
511
491
512
func write( _ data: Data ? , n: UnsafeMutablePointer < Int > ? ) throws {
0 commit comments