@@ -157,7 +157,7 @@ public class ProjectActivity extends Activity implements View.OnClickListener, B
157
157
private boolean minimumPermissionsGranted ;
158
158
159
159
private boolean inMakeCodeActionFlash = false ;
160
- private String applicationHexAbsolutePath ;
160
+ private int applicationSize ;
161
161
private int prepareToFlashResult ;
162
162
163
163
@@ -1246,6 +1246,22 @@ protected void popupFailedToCreateFiles() {
1246
1246
popupClickFlashComplete , popupClickFlashComplete );
1247
1247
}
1248
1248
1249
+ public String getCachePathAppHex () {
1250
+ return this .getCacheDir () + "/application.hex" ;
1251
+ }
1252
+
1253
+ public String getCachePathAppBin () {
1254
+ return this .getCacheDir () + "/application.bin" ;
1255
+ }
1256
+
1257
+ public String getCachePathAppDat () {
1258
+ return this .getCacheDir () + "/application.dat" ;
1259
+ }
1260
+
1261
+ public String getCachePathAppZip () {
1262
+ return this .getCacheDir () + "/update.zip" ;
1263
+ }
1264
+
1249
1265
protected int prepareToFlash () {
1250
1266
logi ("prepareToFlash" );
1251
1267
@@ -1264,27 +1280,33 @@ protected int prepareToFlash() {
1264
1280
// hexAbsolutePath = oldret[0];
1265
1281
// int oldapplicationSize = Integer.parseInt(oldret[1]);
1266
1282
1267
- String [] ret = universalHexToDFU (mProgramToSend .filePath , hardwareType );
1268
- applicationHexAbsolutePath = ret [0 ];
1269
- int applicationSize = Integer .parseInt (ret [1 ]);
1283
+ applicationSize = universalHexToDFU ( mProgramToSend .filePath , hardwareType );
1270
1284
1271
- if (applicationSize == - 1 ) {
1272
- // V1 Hex on a V2
1285
+ if ( applicationSize <= 0 ) {
1286
+ // incompatible hex
1273
1287
return 1 ;
1274
1288
}
1275
1289
1276
- // If V2 create init packet
1277
- String initPacketAbsolutePath = "-1" ;
1278
- if (hardwareType == MICROBIT_V2 ) {
1279
- try {
1280
- initPacketAbsolutePath = createDFUInitPacket (applicationSize );
1281
- String [] files = new String []{initPacketAbsolutePath , applicationHexAbsolutePath };
1282
- createDFUZip (files );
1283
- } catch (IOException e ) {
1284
- Log .v (TAG , "Failed to create init packet" );
1285
- e .printStackTrace ();
1290
+ try {
1291
+ applicationSize = createAppBin ( hardwareType );
1292
+ if ( applicationSize <= 0 ) {
1286
1293
return 2 ;
1287
1294
}
1295
+
1296
+ if ( hardwareType == MICROBIT_V2 ) {
1297
+ // If V2 create init packet and zip package
1298
+ if ( !createAppDat (applicationSize )) {
1299
+ return 2 ;
1300
+ }
1301
+ String [] files = new String []{ getCachePathAppDat (), getCachePathAppBin ()};
1302
+ if ( !createDFUZip (files )) {
1303
+ return 2 ;
1304
+ }
1305
+ }
1306
+ } catch (IOException e ) {
1307
+ Log .v (TAG , "Failed to create init packet" );
1308
+ e .printStackTrace ();
1309
+ return 2 ;
1288
1310
}
1289
1311
1290
1312
return 0 ;
@@ -1306,7 +1328,7 @@ public void startDFUFlash() {
1306
1328
1307
1329
// Start DFU Service
1308
1330
Log .v (TAG , "Start Full DFU" );
1309
- Log .v (TAG , "DFU hex : " + applicationHexAbsolutePath );
1331
+ Log .v (TAG , "DFU bin : " + getCachePathAppBin () );
1310
1332
if (hardwareType == MICROBIT_V2 ) {
1311
1333
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
1312
1334
DfuServiceInitiator .createDfuNotificationChannel (this );
@@ -1321,7 +1343,7 @@ public void startDFUFlash() {
1321
1343
.setRestoreBond (true )
1322
1344
.setKeepBond (true )
1323
1345
.setForeground (true )
1324
- .setZip (this . getCacheDir () + "/update.zip" );
1346
+ .setZip ( getCachePathAppZip () );
1325
1347
final DfuServiceController controller = starter .start (this , DfuService .class );
1326
1348
} else {
1327
1349
if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .O ) {
@@ -1332,7 +1354,7 @@ public void startDFUFlash() {
1332
1354
.setKeepBond (true )
1333
1355
.setForceDfu (true )
1334
1356
.setPacketsReceiptNotificationsEnabled (true )
1335
- .setBinOrHex (DfuBaseService .TYPE_APPLICATION , applicationHexAbsolutePath );
1357
+ .setBinOrHex (DfuBaseService .TYPE_APPLICATION , getCachePathAppBin () );
1336
1358
final DfuServiceController controller = starter .start (this , DfuService .class );
1337
1359
}
1338
1360
}
@@ -1351,7 +1373,7 @@ protected void startPartialFlash() {
1351
1373
}
1352
1374
service = new Intent (application , PartialFlashingService .class );
1353
1375
service .putExtra ("deviceAddress" , currentMicrobit .mAddress );
1354
- service .putExtra ("filepath" , applicationHexAbsolutePath ); // a path or URI must be provided.
1376
+ service .putExtra ("filepath" , getCachePathAppHex () ); // a path or URI must be provided.
1355
1377
service .putExtra ("hardwareType" , hardwareType ); // a path or URI must be provided.
1356
1378
service .putExtra ("pf" , true ); // Enable partial flashing
1357
1379
application .startService (service );
@@ -1362,16 +1384,16 @@ protected void startPartialFlash() {
1362
1384
/**
1363
1385
* Create zip for DFU
1364
1386
*/
1365
- private String createDFUZip (String [] srcFiles ) throws IOException {
1387
+ private boolean createDFUZip (String [] srcFiles ) throws IOException {
1366
1388
byte [] buffer = new byte [1024 ];
1367
1389
1368
- File zipFile = new File (this . getCacheDir () + "/update.zip" );
1390
+ File zipFile = new File ( getCachePathAppZip () );
1369
1391
if (zipFile .exists ()) {
1370
1392
zipFile .delete ();
1371
1393
}
1372
1394
zipFile .createNewFile ();
1373
1395
1374
- FileOutputStream fileOutputStream = new FileOutputStream (this . getCacheDir () + "/update.zip" );
1396
+ FileOutputStream fileOutputStream = new FileOutputStream ( getCachePathAppZip () );
1375
1397
ZipOutputStream zipOutputStream = new ZipOutputStream (fileOutputStream );
1376
1398
1377
1399
for (int i =0 ; i < srcFiles .length ; i ++) {
@@ -1393,105 +1415,102 @@ private String createDFUZip(String[] srcFiles ) throws IOException {
1393
1415
// close the ZipOutputStream
1394
1416
zipOutputStream .close ();
1395
1417
1396
- return this . getCacheDir () + "/update.zip" ;
1418
+ return true ;
1397
1419
}
1398
1420
1399
1421
/**
1400
1422
* Create DFU init packet from HEX
1401
- * @param hexLength
1423
+ * @param appSize
1402
1424
*/
1403
- private String createDFUInitPacket (int hexLength ) throws IOException {
1404
- ByteArrayOutputStream outputInitPacket ;
1405
- outputInitPacket = new ByteArrayOutputStream ();
1406
-
1407
- Log .v (TAG , "DFU App Length: " + hexLength );
1408
-
1409
- outputInitPacket .write ("microbit_app" .getBytes ()); // "microbit_app"
1410
- outputInitPacket .write (new byte []{0x1 , 0 , 0 , 0 }); // Init packet version
1411
- outputInitPacket .write (ByteBuffer .allocate (4 ).order (ByteOrder .LITTLE_ENDIAN ).putInt (hexLength ).array ()); // App size
1412
- outputInitPacket .write (new byte []{0 , 0 , 0 , 0x0 }); // Hash Size. 0: Ignore Hash
1413
- outputInitPacket .write (new byte []{
1414
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1415
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1416
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
1417
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
1418
- }); // Hash
1425
+ private boolean createAppDat ( int appSize ) throws IOException {
1426
+ Log .v (TAG , "createAppDat " + appSize );
1427
+
1428
+ //typedef struct {
1429
+ // uint8_t magic[12]; // identify this struct "microbit_app"
1430
+ // uint32_t version; // version of this struct == 1
1431
+ // uint32_t app_size; // only used for DFU_FW_TYPE_APPLICATION
1432
+ // uint32_t hash_size; // 32 => DFU_HASH_TYPE_SHA256 or zero to bypass hash check
1433
+ // uint8_t hash_bytes[32]; // hash of whole DFU download
1434
+ //} microbit_dfu_app_t;
1435
+ byte [] magic = "microbit_app" .getBytes ();
1436
+ byte [] sizeLE = ByteBuffer .allocate (4 ).order (ByteOrder .LITTLE_ENDIAN ).putInt ( appSize ).array ();
1437
+ byte [] dat = new byte [ 56 ];
1438
+ Arrays .fill ( dat , (byte ) 0 );
1439
+ System .arraycopy ( magic , 0 , dat , 0 , magic .length );
1440
+ dat [ 12 ] = 1 ;
1441
+ System .arraycopy ( sizeLE , 0 , dat , 16 , 4 );
1419
1442
1420
1443
// Write to temp file
1421
- File initPacket = new File (this . getCacheDir () + "/application.dat" );
1422
- if (initPacket .exists ()) {
1423
- initPacket .delete ();
1444
+ File datFile = new File ( getCachePathAppDat () );
1445
+ if ( datFile .exists ()) {
1446
+ datFile .delete ();
1424
1447
}
1425
- initPacket .createNewFile ();
1448
+ if ( !FileUtils .writeBytesToFile ( datFile , dat )) {
1449
+ return false ;
1450
+ }
1451
+ return true ;
1452
+ }
1426
1453
1427
- FileOutputStream outputStream ;
1428
- outputStream = new FileOutputStream (initPacket );
1429
- outputStream .write (outputInitPacket .toByteArray ());
1430
- outputStream .flush ();
1454
+ /**
1455
+ * Create App BIN from HEX
1456
+ */
1457
+ private int createAppBin ( int hardwareType ) throws IOException {
1458
+ File appHexFile = new File ( getCachePathAppHex ());
1459
+ File appBinFile = new File ( getCachePathAppBin ());
1431
1460
1432
- // Should return from here
1433
- return initPacket .getAbsolutePath ();
1461
+ byte [] appHex = FileUtils .readBytesFromFile ( appHexFile );
1462
+ if ( appHex == null ) {
1463
+ return -1 ;
1464
+ }
1465
+ irmHexUtils hexUtils = new irmHexUtils ();
1466
+ int hexBlock = hardwareType == MICROBIT_V1
1467
+ ? irmHexUtils .irmHexBlock01
1468
+ : irmHexUtils .irmHexBlock03 ;
1469
+ if ( !hexUtils .applicationHexToData ( appHex , hexBlock )) {
1470
+ return -1 ;
1471
+ }
1472
+ if ( !FileUtils .writeBytesToFile ( appBinFile , hexUtils .resultData )) {
1473
+ return -1 ;
1474
+ }
1475
+ return hexUtils .resultData .length ;
1434
1476
}
1435
1477
1436
1478
/**
1437
1479
* Process Universal Hex
1438
1480
* @return
1439
1481
*/
1440
- private String [] universalHexToDFU (String inputPath , int hardwareType ) {
1482
+ private int universalHexToDFU ( String inputPath , int hardwareType ) {
1441
1483
logi ("universalHexToDFU" );
1442
1484
try {
1443
- FileInputStream fis = new FileInputStream (inputPath );
1444
- int fileSize = Integer .valueOf (FileUtils .getFileSize (inputPath ));
1445
- byte [] bs = new byte [fileSize ];
1446
- int i = 0 ;
1447
- i = fis .read (bs );
1448
-
1449
- logi ("universalHexToDFU - read file" );
1485
+ File inputHexFile = new File ( inputPath );
1486
+ byte [] inputHex = FileUtils .readBytesFromFile ( inputHexFile );
1487
+ if ( inputHex == null ) {
1488
+ return -1 ;
1489
+ }
1490
+ logi ("universalHexToDFU - file read" );
1450
1491
1451
1492
irmHexUtils irmHexUtil = new irmHexUtils ();
1452
1493
int hexBlock = hardwareType == MICROBIT_V1
1453
1494
? irmHexUtils .irmHexBlock01
1454
1495
: irmHexUtils .irmHexBlock03 ;
1455
- if ( !irmHexUtil .universalHexToApplicationHex ( bs , hexBlock )) {
1456
- return new String []{ "-1" , "-1" } ;
1496
+ if ( !irmHexUtil .universalHexToApplicationHex ( inputHex , hexBlock )) {
1497
+ return - 1 ;
1457
1498
}
1458
- byte [] dataHex = irmHexUtil .resultHex ;
1459
- int application_size = irmHexUtil .resultDataSize ;
1460
1499
logi ("universalHexToDFU - Finished parsing HEX" );
1461
1500
1462
- try {
1463
- File hexToFlash = new File (this .getCacheDir () + "/application.hex" );
1464
- if (hexToFlash .exists ()) {
1465
- hexToFlash .delete ();
1466
- }
1467
- hexToFlash .createNewFile ();
1468
-
1469
- FileOutputStream outputStream = new FileOutputStream (hexToFlash );
1470
- outputStream .write ( dataHex );
1471
- outputStream .flush ();
1472
-
1473
- // Should return from here
1474
- Log .v (TAG , hexToFlash .getAbsolutePath ());
1475
- String [] ret = new String [2 ];
1476
- ret [0 ] = hexToFlash .getAbsolutePath ();
1477
- ret [1 ] = Integer .toString (application_size );
1478
-
1479
- logi ("universalHexToDFU - Finished" );
1480
- return ret ;
1481
- } catch (IOException e ) {
1482
- e .printStackTrace ();
1501
+ File hexFile = new File ( getCachePathAppHex ());
1502
+ if ( !FileUtils .writeBytesToFile ( hexFile , irmHexUtil .resultHex )) {
1503
+ return -1 ;
1483
1504
}
1505
+ // Should return from here
1506
+ logi ("universalHexToDFU - Finished" );
1507
+ return irmHexUtil .resultDataSize ;
1484
1508
1485
- } catch (FileNotFoundException e ) {
1486
- Log .e (TAG , "File not found." );
1487
- e .printStackTrace ();
1488
- } catch (IOException e ) {
1489
- Log .e (TAG , "IO Exception." );
1509
+ } catch ( Exception e ) {
1490
1510
e .printStackTrace ();
1491
1511
}
1492
-
1493
1512
// Should not reach this
1494
- return new String []{ "-1" , "-1" } ;
1513
+ return - 1 ;
1495
1514
}
1496
1515
1497
1516
// /**
0 commit comments