15
15
import android .content .Context ;
16
16
import android .content .Intent ;
17
17
import android .content .IntentFilter ;
18
- import android .os .Handler ;
19
18
import android .os .SystemClock ;
20
19
import android .util .Log ;
21
20
37
36
// A service that interacts with the BLE device via the Android BLE API.
38
37
public abstract class PartialFlashingBaseService extends IntentService {
39
38
39
+ public static final String DFU_BROADCAST_ERROR = "no.nordicsemi.android.dfu.broadcast.BROADCAST_ERROR" ;
40
+
40
41
public static final UUID PARTIAL_FLASH_CHARACTERISTIC = UUID .fromString ("e97d3b10-251d-470a-a062-fa1922dfa9a8" );
41
42
public static final UUID PARTIAL_FLASHING_SERVICE = UUID .fromString ("e97dd91d-251d-470a-a062-fa1922dfa9a8" );
42
43
public static final String PXT_MAGIC = "708E3B92C615A841C49866C975EE5197" ;
@@ -54,16 +55,15 @@ public abstract class PartialFlashingBaseService extends IntentService {
54
55
private BluetoothGatt mBluetoothGatt ;
55
56
private int mConnectionState = STATE_DISCONNECTED ;
56
57
private BluetoothDevice device ;
57
- BluetoothGattService Service ;
58
- BluetoothGattService dfuService ;
59
-
60
- BluetoothGattCharacteristic partialFlashCharacteristic ;
61
58
62
59
private final Object lock = new Object ();
60
+ private final Object region_lock = new Object ();
63
61
64
62
private static final byte PACKET_STATE_WAITING = 0 ;
65
63
private static final byte PACKET_STATE_SENT = (byte )0xFF ;
66
64
private static final byte PACKET_STATE_RETRANSMIT = (byte )0xAA ;
65
+ private static final byte PACKET_STATE_COMPLETE_FLASH = (byte ) 0xCF ;
66
+
67
67
private byte packetState = PACKET_STATE_WAITING ;
68
68
69
69
// Used to lock the program state while we wait for a Bluetooth operation to complete
@@ -151,17 +151,6 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) {
151
151
} else {
152
152
Log .w (TAG , "onServicesDiscovered received: " + status );
153
153
}
154
-
155
- Service = gatt .getService (PARTIAL_FLASHING_SERVICE );
156
- if (Service == null ) {
157
- Log .e (TAG , "pf service not found!" );
158
- }
159
-
160
- dfuService = gatt .getService (MICROBIT_DFU_SERVICE );
161
- if (dfuService == null ) {
162
- Log .e (TAG , "dfu service not found!" );
163
- }
164
-
165
154
synchronized (lock ) {
166
155
lock .notifyAll ();
167
156
}
@@ -187,7 +176,7 @@ public void onCharacteristicWrite(BluetoothGatt gatt,
187
176
Log .v (TAG , "GATT status: Success" );
188
177
} else {
189
178
// TODO Attempt to resend?
190
- Log .v (TAG , "GATT status:" + Integer .toString (status ));
179
+ Log .v (TAG , "GATT WRITE ERROR. status:" + Integer .toString (status ));
191
180
}
192
181
synchronized (lock ) {
193
182
lock .notifyAll ();
@@ -218,16 +207,19 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris
218
207
if (notificationValue [1 ] == REGION_DAL )
219
208
dalHash = bytesToHex (hash );
220
209
210
+ synchronized (region_lock ) {
211
+ region_lock .notifyAll ();
212
+ }
213
+
221
214
break ;
222
215
}
223
216
case FLASH_COMMAND : {
224
217
packetState = notificationValue [1 ];
218
+ synchronized (lock ) {
219
+ lock .notifyAll ();
220
+ }
225
221
}
226
222
}
227
-
228
- synchronized (lock ) {
229
- lock .notifyAll ();
230
- }
231
223
}
232
224
233
225
@ Override
@@ -285,8 +277,7 @@ private void sendProgressBroadcastComplete() {
285
277
}
286
278
287
279
// Write to BLE Flash Characteristic
288
- public Boolean writePartialFlash (byte data []){
289
-
280
+ public Boolean writePartialFlash (BluetoothGattCharacteristic partialFlashCharacteristic , byte [] data ){
290
281
partialFlashCharacteristic .setWriteType (BluetoothGattCharacteristic .WRITE_TYPE_NO_RESPONSE );
291
282
partialFlashCharacteristic .setValue (data );
292
283
boolean status = mBluetoothGatt .writeCharacteristic (partialFlashCharacteristic );
@@ -302,6 +293,8 @@ public int attemptPartialFlash(String filePath) {
302
293
int progressBar = 0 ;
303
294
int numOfLines = 0 ;
304
295
296
+ sendProgressBroadcastStart ();
297
+
305
298
try {
306
299
307
300
Log .v (TAG , "attemptPartialFlash()" );
@@ -323,14 +316,21 @@ public int attemptPartialFlash(String filePath) {
323
316
Log .v (TAG , "Total lines: " + numOfLines );
324
317
325
318
// Ready to flash!
326
- sendProgressBroadcastStart ();
327
319
// Loop through data
328
320
String hexData ;
329
321
int packetNum = 0 ;
330
322
int lineCount = 0 ;
323
+
324
+ // Characteristic
325
+ BluetoothGattService pfService = mBluetoothGatt .getService (PARTIAL_FLASHING_SERVICE );
326
+ BluetoothGattCharacteristic partialFlashCharacteristic = pfService .getCharacteristic (PARTIAL_FLASH_CHARACTERISTIC );
327
+
331
328
while (true ){
332
- // Timeout if total is > 60 seconds
333
- if (SystemClock .elapsedRealtime () - startTime > 60000 ) return PF_FAILED ;
329
+ // Timeout if total is > 30 seconds
330
+ if (SystemClock .elapsedRealtime () - startTime > 60000 ) {
331
+ Log .v (TAG , "Partial flashing has timed out" );
332
+ return PF_FAILED ;
333
+ }
334
334
335
335
// Get next data to write
336
336
hexData = hex .getDataFromIndex (magicIndex + lineCount );
@@ -354,7 +354,7 @@ public int attemptPartialFlash(String filePath) {
354
354
355
355
// Write without response
356
356
// Wait for previous write to complete
357
- boolean writeStatus = writePartialFlash (chunk );
357
+ boolean writeStatus = writePartialFlash (partialFlashCharacteristic , chunk );
358
358
359
359
// Sleep after 4 packets
360
360
count ++;
@@ -371,11 +371,11 @@ public int attemptPartialFlash(String filePath) {
371
371
long timeout = SystemClock .elapsedRealtime ();
372
372
while (packetState == PACKET_STATE_WAITING ) {
373
373
synchronized (lock ) {
374
- lock .wait (1 );
374
+ lock .wait (5000 );
375
375
}
376
376
377
377
// Timeout if longer than 5 seconds
378
- if ((SystemClock .elapsedRealtime () - timeout ) > 5000 ) return PF_FAILED ;
378
+ if ((SystemClock .elapsedRealtime () - timeout ) > 5000 )return PF_FAILED ;
379
379
}
380
380
381
381
packetState = PACKET_STATE_WAITING ;
@@ -404,10 +404,11 @@ public int attemptPartialFlash(String filePath) {
404
404
405
405
// Write End of Flash packet
406
406
byte [] endOfFlashPacket = {(byte )0x02 };
407
- writePartialFlash (endOfFlashPacket );
407
+ writePartialFlash (partialFlashCharacteristic , endOfFlashPacket );
408
408
409
409
// Finished Writing
410
410
Log .v (TAG , "Flash Complete" );
411
+ packetState = PACKET_STATE_COMPLETE_FLASH ;
411
412
sendProgressBroadcast (100 );
412
413
sendProgressBroadcastComplete ();
413
414
@@ -456,7 +457,7 @@ private boolean initialize(String deviceId) throws InterruptedException {
456
457
device = mBluetoothAdapter .getRemoteDevice (deviceId );
457
458
}
458
459
459
- mBluetoothGatt = device .connectGatt (this , false , mGattCallback );
460
+ mBluetoothGatt = device .connectGatt (this , true , mGattCallback );
460
461
461
462
//check mBluetoothGatt is available
462
463
if (mBluetoothGatt == null ) {
@@ -469,8 +470,14 @@ private boolean initialize(String deviceId) throws InterruptedException {
469
470
}
470
471
471
472
// Get Characteristic
472
- partialFlashCharacteristic = Service . getCharacteristic ( PARTIAL_FLASH_CHARACTERISTIC );
473
+ BluetoothGattService pfService = mBluetoothGatt . getService ( PARTIAL_FLASHING_SERVICE );
473
474
475
+ if (pfService == null ) {
476
+ // Probably not in pairing mode
477
+ return false ;
478
+ }
479
+
480
+ BluetoothGattCharacteristic partialFlashCharacteristic = pfService .getCharacteristic (PARTIAL_FLASH_CHARACTERISTIC );
474
481
475
482
// Set up BLE notification
476
483
if (!mBluetoothGatt .setCharacteristicNotification (partialFlashCharacteristic , true )){
@@ -479,25 +486,19 @@ private boolean initialize(String deviceId) throws InterruptedException {
479
486
Log .v (TAG , "Notifications enabled" );
480
487
}
481
488
482
- // Set up BLE priority
483
- if (mBluetoothGatt .requestConnectionPriority (BluetoothGatt .CONNECTION_PRIORITY_HIGH )){
484
- Log .w (TAG , "Failed to set up priority" );
485
- } else {
486
- Log .v (TAG , "High priority" );
487
- }
488
-
489
489
BluetoothGattDescriptor descriptor = partialFlashCharacteristic .getDescriptor (CLIENT_CHARACTERISTIC_CONFIG );
490
490
descriptor .setValue (ENABLE_NOTIFICATION_VALUE );
491
491
boolean res = mBluetoothGatt .writeDescriptor (descriptor );
492
492
493
493
synchronized (lock ) {
494
- lock .wait (2000 );
494
+ lock .wait ();
495
495
}
496
496
497
497
return true ;
498
498
}
499
-
499
+
500
500
public static final String BROADCAST_PF_FAILED = "org.microbit.android.partialflashing.broadcast.BROADCAST_PF_FAILED" ;
501
+ public static final String BROADCAST_PF_ATTEMPT_DFU = "org.microbit.android.partialflashing.broadcast.BROADCAST_PF_ATTEMPT_DFU" ;
501
502
502
503
@ Override
503
504
protected void onHandleIntent (@ Nullable Intent intent ) {
@@ -507,31 +508,52 @@ protected void onHandleIntent(@Nullable Intent intent) {
507
508
final String deviceAddress = intent .getStringExtra ("deviceAddress" );
508
509
509
510
Log .v (TAG , "Initialise" );
511
+ boolean initialize_ret = false ;
510
512
try {
511
- initialize (deviceAddress );
513
+ initialize_ret = initialize (deviceAddress );
512
514
} catch (InterruptedException e ) {
513
515
e .printStackTrace ();
514
516
}
515
517
Log .v (TAG , "/Initialise" );
516
- readMemoryMap ();
518
+
517
519
// If fails attempt full flash
520
+ if (!initialize_ret ) {
521
+ // Partial flashing started but failed. Need to PF or USB flash to fix
522
+ final Intent broadcast = new Intent (BROADCAST_PF_FAILED );
523
+ LocalBroadcastManager .getInstance (this ).sendBroadcast (broadcast );
524
+ return ;
525
+ }
526
+
527
+ // Get Memory Map from Microbit
528
+ try {
529
+ readMemoryMap ();
530
+ } catch (InterruptedException e ) {
531
+ e .printStackTrace ();
532
+ }
518
533
int pf_result = attemptPartialFlash (filePath );
519
- if (( pf_result == PF_ATTEMPT_DFU ) || Service == null )
534
+ if (pf_result == PF_ATTEMPT_DFU )
520
535
{
521
536
Log .v (TAG , "Partial Flashing not possible" );
522
-
537
+ BluetoothGattService dfuService = mBluetoothGatt . getService ( MICROBIT_DFU_SERVICE );
523
538
// Write Characteristic to enter DFU mode
539
+ if (dfuService == null ) {
540
+ Log .v (TAG , "DFU Service is null" );
541
+ final Intent broadcast = new Intent (DFU_BROADCAST_ERROR );
542
+ LocalBroadcastManager .getInstance (this ).sendBroadcast (broadcast );
543
+ return ;
544
+ }
524
545
BluetoothGattCharacteristic microbitDFUCharacteristic = dfuService .getCharacteristic (MICROBIT_DFU_CHARACTERISTIC );
525
546
byte payload [] = {0x01 };
526
547
microbitDFUCharacteristic .setValue (payload );
527
548
boolean status = mBluetoothGatt .writeCharacteristic (microbitDFUCharacteristic );
528
549
Log .v (TAG , "MicroBitDFU :: Enter DFU Result " + status );
529
550
530
- // Wait
531
- try {
532
- Thread .sleep (500 );
533
- } catch (InterruptedException e ) {
534
- e .printStackTrace ();
551
+ synchronized (lock ) {
552
+ try {
553
+ lock .wait ();
554
+ } catch (InterruptedException e ) {
555
+ e .printStackTrace ();
556
+ }
535
557
}
536
558
537
559
// Refresh services
@@ -545,13 +567,21 @@ protected void onHandleIntent(@Nullable Intent intent) {
545
567
// Log it
546
568
}
547
569
548
- final Intent broadcast = new Intent ( BROADCAST_PF_FAILED );
549
-
570
+ Log . v ( TAG , "Send Intent: BROADCAST_PF_ATTEMPT_DFU" );
571
+ final Intent broadcast = new Intent ( BROADCAST_PF_ATTEMPT_DFU );
550
572
LocalBroadcastManager .getInstance (this ).sendBroadcast (broadcast );
573
+ return ;
551
574
} else if (pf_result == PF_FAILED ) {
552
575
// Partial flashing started but failed. Need to PF or USB flash to fix
553
576
final Intent broadcast = new Intent (BROADCAST_PF_FAILED );
554
- startActivity (broadcast );
577
+ LocalBroadcastManager .getInstance (this ).sendBroadcast (broadcast );
578
+ return ;
579
+ }
580
+
581
+ // Check complete before leaving intent
582
+ if (packetState != PACKET_STATE_COMPLETE_FLASH ) {
583
+ final Intent broadcast = new Intent (BROADCAST_PF_FAILED );
584
+ LocalBroadcastManager .getInstance (this ).sendBroadcast (broadcast );
555
585
}
556
586
557
587
Log .v (TAG , "onHandleIntent End" );
@@ -560,22 +590,26 @@ protected void onHandleIntent(@Nullable Intent intent) {
560
590
/*
561
591
Read Memory Map from the MB
562
592
*/
563
- private Boolean readMemoryMap () {
593
+ private Boolean readMemoryMap () throws InterruptedException {
564
594
boolean status ; // Gatt Status
565
595
596
+ BluetoothGattService pfService = mBluetoothGatt .getService (PARTIAL_FLASHING_SERVICE );
597
+ BluetoothGattCharacteristic partialFlashCharacteristic = pfService .getCharacteristic (PARTIAL_FLASH_CHARACTERISTIC );
598
+
566
599
try {
567
600
for (int i = 0 ; i < 3 ; i ++)
568
601
{
569
602
// Get Start, End, and Hash of each Region
570
603
// Request Region
571
604
byte [] payload = {REGION_INFO_COMMAND , (byte )i };
572
605
partialFlashCharacteristic .setValue (payload );
573
- notificationReceived = false ;
574
606
status = mBluetoothGatt .writeCharacteristic (partialFlashCharacteristic );
575
- Log .v (TAG , "Request Region " + i );
576
- synchronized (lock ) {
577
- lock .wait ();
607
+ Log .v (TAG , "Request Region " + i + " Status: " + status );
608
+
609
+ synchronized (region_lock ) {
610
+ region_lock .wait ();
578
611
}
612
+
579
613
}
580
614
581
615
0 commit comments