Skip to content

Commit 2b58494

Browse files
committed
Modify connect & discover; update hex decoding for longer lines.
1 parent c9fa5c9 commit 2b58494

File tree

1 file changed

+174
-119
lines changed

1 file changed

+174
-119
lines changed

src/main/java/org/microbit/android/partialflashing/PartialFlashingBaseService.java

Lines changed: 174 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ public abstract class PartialFlashingBaseService extends IntentService {
9696
boolean python = false;
9797
String dalHash;
9898

99+
long code_startAddress = 0;
100+
101+
long code_endAddress = 0;
102+
99103
// Partial Flashing Commands
100104
private static final byte REGION_INFO_COMMAND = 0x0;
101105
private static final byte FLASH_COMMAND = 0x1;
@@ -150,7 +154,6 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status,
150154
String intentAction;
151155
if (newState == BluetoothProfile.STATE_CONNECTED) {
152156

153-
final boolean success = gatt.discoverServices();
154157
mConnectionState = STATE_CONNECTED;
155158

156159
/* Taken from Nordic. See reasoning here: https://github.com/NordicSemiconductor/Android-DFU-Library/blob/e0ab213a369982ae9cf452b55783ba0bdc5a7916/dfu/src/main/java/no/nordicsemi/android/dfu/DfuBaseService.java#L888 */
@@ -165,11 +168,10 @@ public void onConnectionStateChange(BluetoothGatt gatt, int status,
165168
}
166169
Log.v(TAG, "Bond timeout");
167170
}
168-
// After 1.6s the services are already discovered so the following gatt.discoverServices() finishes almost immediately.
169-
// NOTE: This also works with shorted waiting time. The gatt.discoverServices() must be called after the indication is received which is
171+
// NOTE: This also works with shorted waiting time. The gatt.discoverServices() must be called after the indication is received which is
170172
// about 600ms after establishing connection. Values 600 - 1600ms should be OK.
171173
}
172-
gatt.discoverServices();
174+
final boolean success = gatt.discoverServices();
173175

174176
if (!success) {
175177
Log.e(TAG,"ERROR_SERVICE_DISCOVERY_NOT_STARTED");
@@ -255,6 +257,18 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris
255257
byte[] endAddress = Arrays.copyOfRange(notificationValue, 6, 10);
256258
Log.v(TAG, "startAddress: " + bytesToHex(startAddress) + " endAddress: " + bytesToHex(endAddress));
257259

260+
if ( notificationValue[1] == REGION_MAKECODE) {
261+
code_startAddress = Byte.toUnsignedLong(startAddress[0])
262+
+ Byte.toUnsignedLong(startAddress[0]) * 256
263+
+ Byte.toUnsignedLong(startAddress[0]) * 256 * 256
264+
+ Byte.toUnsignedLong(startAddress[0]) * 256 * 256 * 256;
265+
266+
code_endAddress = Byte.toUnsignedLong(endAddress[0])
267+
+ Byte.toUnsignedLong(endAddress[0]) * 256
268+
+ Byte.toUnsignedLong(endAddress[0]) * 256 * 256
269+
+ Byte.toUnsignedLong(endAddress[0]) * 256 * 256 * 256;
270+
}
271+
258272
byte[] hash = Arrays.copyOfRange(notificationValue, 10, 18);
259273
Log.v(TAG, "Hash: " + bytesToHex(hash));
260274

@@ -351,11 +365,6 @@ public Boolean writePartialFlash(BluetoothGattCharacteristic partialFlashCharact
351365

352366
public int attemptPartialFlash(String filePath) {
353367
Log.v(TAG, "Flashing: " + filePath);
354-
long startTime = SystemClock.elapsedRealtime();
355-
356-
int count = 0;
357-
int progressBar = 0;
358-
int numOfLines = 0;
359368

360369
sendProgressBroadcastStart();
361370

@@ -365,30 +374,49 @@ public int attemptPartialFlash(String filePath) {
365374
Log.v(TAG, filePath);
366375
HexUtils hex = new HexUtils(filePath);
367376
Log.v(TAG, "searchForData()");
377+
String hash = "";
368378
int magicIndex = hex.searchForData(PXT_MAGIC);
379+
if (magicIndex > -1) {
380+
python = false;
381+
String magicData = hex.getDataFromIndex(magicIndex);
382+
int next = magicData.indexOf(PXT_MAGIC) + PXT_MAGIC.length();
383+
if ( next < magicData.length()) {
384+
hash = magicData.substring( next);
385+
}
386+
if ( hash.length() < 16) {
387+
String nextData = hex.getDataFromIndex( magicIndex + 1);
388+
hash = hash + nextData.substring( 0, 16 - hash.length());
389+
}
390+
} else {
391+
// magicIndex = hex.searchForDataRegEx(UPY_MAGIC);
392+
// python = true;
393+
}
369394

370395
if (magicIndex == -1) {
371-
magicIndex = hex.searchForDataRegEx(UPY_MAGIC);
372-
python = true;
396+
Log.v(TAG, "No magic");
397+
return PF_ATTEMPT_DFU;
373398
}
374399

375-
Log.v(TAG, "/searchForData() = " + magicIndex);
376-
if (magicIndex > -1) {
377-
378-
Log.v(TAG, "Found PXT_MAGIC");
379-
380-
// Get Memory Map from Microbit
381-
try {
382-
Log.v(TAG, "readMemoryMap()");
383-
readMemoryMap();
384-
} catch (InterruptedException e) {
385-
e.printStackTrace();
400+
Log.v(TAG, "Found PXT_MAGIC at " + magicIndex);
401+
402+
// Get Memory Map from Microbit
403+
try {
404+
Log.v(TAG, "readMemoryMap()");
405+
readMemoryMap();
406+
} catch (InterruptedException e) {
407+
e.printStackTrace();
408+
}
409+
410+
// Compare DAL hash
411+
if( !python) {
412+
if (!hash.equals(dalHash)) {
413+
Log.v(TAG, hash + " " + (dalHash));
414+
return PF_ATTEMPT_DFU;
386415
}
387-
388-
// Find DAL hash
389-
if(python) magicIndex = magicIndex - 3;
416+
} else {
417+
magicIndex = magicIndex - 3;
390418

391-
int record_length = hex.getRecordDataLengthFromIndex(magicIndex );
419+
int record_length = hex.getRecordDataLengthFromIndex(magicIndex);
392420
Log.v(TAG, "Length of record: " + record_length);
393421

394422
int magic_offset = (record_length == 64) ? 32 : 0;
@@ -397,131 +425,158 @@ public int attemptPartialFlash(String filePath) {
397425

398426
Log.v(TAG, hashes);
399427

400-
if(hashes.charAt(3) == '2') {
428+
if (hashes.charAt(3) == '2') {
401429
// Uses a hash pointer. Create regex and extract from hex
402430
String regEx = ".*" +
403431
dalHash +
404432
".*";
405433
int hashIndex = hex.searchForDataRegEx(regEx);
406434

407435
// TODO Uses CRC of hash
408-
if(hashIndex == -1 ) {
436+
if (hashIndex == -1) {
409437
// return PF_ATTEMPT_DFU;
410438
}
411439
// hashes = hex.getDataFromIndex(hashIndex);
412440
// Log.v(TAG, "hash: " + hashes);
413-
} else if(!hashes.substring(magic_offset, magic_offset + 16).equals(dalHash)) {
414-
Log.v(TAG, hashes.substring(magic_offset, magic_offset + 16) + " " + (dalHash));
415-
return PF_ATTEMPT_DFU;
441+
} else if (!hashes.substring(magic_offset, magic_offset + 16).equals(dalHash)) {
442+
Log.v(TAG, hashes.substring(magic_offset, magic_offset + 16) + " " + (dalHash));
443+
return PF_ATTEMPT_DFU;
416444
}
445+
}
417446

418-
numOfLines = hex.numOfLines() - magicIndex;
419-
Log.v(TAG, "Total lines: " + numOfLines);
420-
421-
// Ready to flash!
422-
// Loop through data
423-
String hexData;
424-
int packetNum = 0;
425-
int lineCount = 0;
447+
int count = 0;
448+
int numOfLines = hex.numOfLines() - magicIndex;
449+
Log.v(TAG, "Total lines: " + numOfLines);
450+
451+
int magicLo = hex.getRecordAddressFromIndex(magicIndex);
452+
int magicHi = hex.getSegmentAddress(magicIndex);
453+
long magicA = (long) magicLo + (long) magicHi * 256 * 256;
454+
455+
// Ready to flash!
456+
// Loop through data
457+
int packetNum = 0;
458+
int lineCount = 0;
459+
int part = 0;
460+
int line0 = 0;
461+
int part0 = 0;
462+
463+
int addrLo = hex.getRecordAddressFromIndex(magicIndex + lineCount);
464+
int addrHi = hex.getSegmentAddress(magicIndex + lineCount);
465+
long addr = (long) addrLo + (long) addrHi * 256 * 256;
466+
467+
String hexData;
468+
String partData;
469+
470+
Log.v(TAG, "enter flashing loop");
471+
472+
long startTime = SystemClock.elapsedRealtime();
473+
while (true) {
474+
// Timeout if total is > 30 seconds
475+
if(SystemClock.elapsedRealtime() - startTime > 60000) {
476+
Log.v(TAG, "Partial flashing has timed out");
477+
return PF_FAILED;
478+
}
426479

427-
Log.v(TAG, "enter flashing loop");
480+
// Check if EOF
481+
if(hex.getRecordTypeFromIndex(magicIndex + lineCount) != 0) {
482+
break;
483+
}
428484

429-
while(true){
430-
// Timeout if total is > 30 seconds
431-
if(SystemClock.elapsedRealtime() - startTime > 60000) {
432-
Log.v(TAG, "Partial flashing has timed out");
433-
return PF_FAILED;
434-
}
485+
addrLo = hex.getRecordAddressFromIndex(magicIndex + lineCount);
486+
addrHi = hex.getSegmentAddress(magicIndex + lineCount);
487+
addr = (long) addrLo + (long) addrHi * 256 * 256;
435488

436-
// Get next data to write
437-
hexData = hex.getDataFromIndex(magicIndex + lineCount);
489+
hexData = hex.getDataFromIndex( magicIndex + lineCount);
490+
if ( part + 32 > hexData.length()) {
491+
partData = hexData.substring( part);
492+
} else {
493+
partData = hexData.substring(part, part + 32);
494+
}
495+
Log.v(TAG, partData);
496+
497+
// recordToByteArray() build a PF command block with the data
498+
int offsetToSend = 0;
499+
if (count == 0) {
500+
offsetToSend = addrLo + part;
501+
} else if (count == 1) {
502+
offsetToSend = addrHi;
503+
}
504+
byte chunk[] = HexUtils.recordToByteArray(partData, offsetToSend, packetNum);
438505

439-
Log.v(TAG, hexData);
506+
// Write without response
507+
// Wait for previous write to complete
508+
boolean writeStatus = writePartialFlash(partialFlashCharacteristic, chunk);
440509

441-
// Check if EOF
442-
if(hex.getRecordTypeFromIndex(magicIndex + lineCount) != 0) break;
510+
if ( count == 0)
511+
{
512+
line0 = lineCount;
513+
part0 = part;
514+
}
443515

444-
// Split into bytes
445-
int offsetToSend = 0;
446-
if(count == 0) {
447-
offsetToSend = hex.getRecordAddressFromIndex(magicIndex + lineCount);
448-
}
516+
// Sleep after 4 packets
517+
count++;
518+
if ( count == 4){
519+
count = 0;
449520

450-
if(count == 1) {
451-
offsetToSend = hex.getSegmentAddress(magicIndex + lineCount);
452-
}
521+
// Wait for notification
522+
Log.v(TAG, "Wait for notification");
453523

454-
byte chunk[] = HexUtils.recordToByteArray(hexData, offsetToSend, packetNum);
455-
456-
// Write without response
457-
// Wait for previous write to complete
458-
boolean writeStatus = writePartialFlash(partialFlashCharacteristic, chunk);
459-
460-
// Sleep after 4 packets
461-
count++;
462-
if(count == 4){
463-
count = 0;
464-
465-
// Wait for notification
466-
Log.v(TAG, "Wait for notification");
467-
468-
// Send broadcast while waiting
469-
int percent = Math.round((float)100 * ((float)(lineCount) / (float)(numOfLines)));
470-
sendProgressBroadcast(percent);
471-
472-
long timeout = SystemClock.elapsedRealtime();
473-
while(packetState == PACKET_STATE_WAITING) {
474-
synchronized (lock) {
475-
lock.wait(5000);
476-
}
524+
// Send broadcast while waiting
525+
int percent = Math.round((float)100 * ((float)(lineCount) / (float)(numOfLines)));
526+
sendProgressBroadcast(percent);
477527

478-
// Timeout if longer than 5 seconds
479-
if((SystemClock.elapsedRealtime() - timeout) > 5000)return PF_FAILED;
528+
long timeout = SystemClock.elapsedRealtime();
529+
while(packetState == PACKET_STATE_WAITING) {
530+
synchronized (lock) {
531+
lock.wait(5000);
480532
}
481533

482-
packetState = PACKET_STATE_WAITING;
483-
484-
Log.v(TAG, "/Wait for notification");
485-
486-
} else {
487-
Thread.sleep(5);
534+
// Timeout if longer than 5 seconds
535+
if((SystemClock.elapsedRealtime() - timeout) > 5000)
536+
return PF_FAILED;
488537
}
489538

490-
// If notification is retransmit -> retransmit last block.
491-
// Else set start of new block
492-
if(packetState == PACKET_STATE_RETRANSMIT) {
493-
lineCount = lineCount - 4;
494-
} else {
495-
// Next line
496-
lineCount = lineCount + 1;
497-
}
539+
packetState = PACKET_STATE_WAITING;
498540

499-
// Always increment packet #
500-
packetNum = packetNum + 1;
541+
Log.v(TAG, "/Wait for notification");
501542

543+
} else {
544+
Thread.sleep(5);
502545
}
503546

547+
// If notification is retransmit -> retransmit last block.
548+
// Else set start of new block
549+
if(packetState == PACKET_STATE_RETRANSMIT) {
550+
lineCount = line0;
551+
part = part0;
552+
} else {
553+
// Next part
554+
part = part + partData.length();
555+
if ( part >= hexData.length()) {
556+
part = 0;
557+
lineCount = lineCount + 1;
558+
}
559+
}
504560

505-
506-
// Write End of Flash packet
507-
byte[] endOfFlashPacket = {(byte)0x02};
508-
writePartialFlash(partialFlashCharacteristic, endOfFlashPacket);
509-
510-
// Finished Writing
511-
Log.v(TAG, "Flash Complete");
512-
packetState = PACKET_STATE_COMPLETE_FLASH;
513-
sendProgressBroadcast(100);
514-
sendProgressBroadcastComplete();
515-
516-
// Time execution
517-
long endTime = SystemClock.elapsedRealtime();
518-
long elapsedMilliSeconds = endTime - startTime;
519-
double elapsedSeconds = elapsedMilliSeconds / 1000.0;
520-
Log.v(TAG, "Flash Time: " + Float.toString((float)elapsedSeconds) + " seconds");
521-
522-
} else {
523-
return PF_ATTEMPT_DFU;
561+
// Always increment packet #
562+
packetNum = packetNum + 1;
524563
}
564+
565+
// Write End of Flash packet
566+
byte[] endOfFlashPacket = {(byte)0x02};
567+
writePartialFlash(partialFlashCharacteristic, endOfFlashPacket);
568+
569+
// Finished Writing
570+
Log.v(TAG, "Flash Complete");
571+
packetState = PACKET_STATE_COMPLETE_FLASH;
572+
sendProgressBroadcast(100);
573+
sendProgressBroadcastComplete();
574+
575+
// Time execution
576+
long endTime = SystemClock.elapsedRealtime();
577+
long elapsedMilliSeconds = endTime - startTime;
578+
double elapsedSeconds = elapsedMilliSeconds / 1000.0;
579+
Log.v(TAG, "Flash Time: " + Float.toString((float)elapsedSeconds) + " seconds");
525580
} catch (IOException e) {
526581
e.printStackTrace();
527582
} catch (InterruptedException e) {

0 commit comments

Comments
 (0)