Skip to content

Commit 3e8c7c0

Browse files
committed
Initial commit
0 parents  commit 3e8c7c0

File tree

10 files changed

+843
-0
lines changed

10 files changed

+843
-0
lines changed

build.gradle

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apply plugin: 'com.android.library'
2+
3+
android {
4+
compileSdkVersion 23
5+
buildToolsVersion '22.0.0'
6+
7+
defaultConfig {
8+
minSdkVersion 19
9+
targetSdkVersion 22
10+
}
11+
12+
buildTypes {
13+
release {
14+
minifyEnabled false
15+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
16+
}
17+
}
18+
}
19+
20+
dependencies {
21+
compile fileTree(dir: 'libs', include: ['*.jar'])
22+
}
23+
24+

src/.DS_Store

6 KB
Binary file not shown.

src/main/.DS_Store

6 KB
Binary file not shown.

src/main/AndroidManifest.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2+
package="com.samsung.dfulibrary"
3+
android:versionCode="1"
4+
android:versionName="1.0" >
5+
6+
<uses-sdk
7+
android:minSdkVersion="18"
8+
android:targetSdkVersion="21" />
9+
<uses-permission android:name="android.permission.BLUETOOTH" />
10+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
11+
</manifest>

src/main/java/.DS_Store

6 KB
Binary file not shown.

src/main/java/org/microbit/.DS_Store

6 KB
Binary file not shown.
Binary file not shown.
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
package org.microbit.android.hexutils
2+
3+
import android.util.Log;
4+
5+
import java.io.BufferedReader;
6+
import java.io.EOFException;
7+
import java.io.FileInputStream;
8+
import java.io.FileNotFoundException;
9+
import java.io.IOException;
10+
import java.io.InputStreamReader;
11+
import java.io.InterruptedIOException;
12+
13+
/**
14+
* Created by Sam Kent on 01/11/2017.
15+
*
16+
* A Class to manipulate micro:bit hex files
17+
* Focused towards stripping a file down to it's PXT section for use in Partial Flashing
18+
*
19+
*/
20+
21+
public class HexUtils {
22+
private final static String TAG = HexUtils.class.getSimpleName();
23+
24+
private final static String PXT_MAGIC = "708E3B92C615A841C49866C975EE5197";
25+
26+
private final static int INIT = 0;
27+
private final static int INVALID_FILE = 1;
28+
private final static int NO_PARTIAL_FLASH = 2;
29+
public int status = INIT;
30+
31+
FileInputStream fis = null;
32+
BufferedReader reader = null;
33+
List<String> hexLines = new ArrayList<String>();
34+
35+
int BUFFER_LIMIT = 10000;
36+
37+
String templateHash;
38+
String programHash;
39+
int sectionAddress;
40+
int magicAddress;
41+
42+
int currentRecordType = 0;
43+
int currentRecordOffset = 0;
44+
45+
int magicLines = 0;
46+
47+
/*
48+
Unused initializer
49+
*/
50+
public void HexUtils(String filePath){
51+
// Hex Utils initialization
52+
// Open File
53+
if(!openHexFile(filePath)){
54+
status = INVALID_FILE;
55+
}
56+
}
57+
58+
/*
59+
A function to open a hex file for reading
60+
@param filePath - A string locating the hex file in use
61+
@return true - if file opens
62+
false - if file cannot be opened
63+
*/
64+
public Boolean openHexFile(String filePath) throws IOException {
65+
// Open connection to hex file
66+
try {
67+
fis = new FileInputStream(filePath);
68+
} catch (FileNotFoundException e) {
69+
e.printStackTrace();
70+
return false;
71+
}
72+
73+
// Create reader for hex file
74+
reader = new BufferedReader(new InputStreamReader(fis));
75+
76+
while((String line = reader.readLine()) != null) {
77+
hexLines.add(line);
78+
}
79+
reader.close();
80+
return true;
81+
}
82+
83+
public int searchForData(String search) throws IOException {
84+
// Iterate through
85+
Iterator i = hexLines.iterator();
86+
while (i.hasNext()) {
87+
// Have to call nextIndex() before next()
88+
int index = i.nextIndex();
89+
90+
// Return index if successful
91+
if(i.next().contains(search)){ return index; }
92+
}
93+
94+
// Return -1 if no match
95+
return -1;
96+
}
97+
98+
public String getDataFromIndex(int index) throws IOException {
99+
return getRecordData(hexLines.get(index));
100+
}
101+
102+
public int getRecordTypeFromIndex(int index) throws IOException {
103+
return getRecordType(hexLines.get(index);
104+
}
105+
106+
public int getRecordAddressFromIndex(int index) throws IOException {
107+
return getRecordOffset(hexLines.get(index));
108+
}
109+
110+
public int getSegmentAddress(int index) throws IOException {
111+
// Look backwards to find current segment address
112+
int segmentAddress = -1;
113+
int cur = index;
114+
while(segmentAddress == -1) {
115+
if(getRecordTypeFromIndex(cur) == 4)
116+
break;
117+
cur--;
118+
}
119+
120+
// Return segment address
121+
return Integer.parseInt(getRecordData(hexLines.get(cur)), 16);
122+
}
123+
124+
public Boolean findMagic(String magic) throws IOException {
125+
String record;
126+
127+
try {
128+
while ((record = reader.readLine()) != null) {
129+
// Inc magic lines
130+
magicLines++;
131+
132+
// Record Type
133+
switch(getRecordType(record)) {
134+
case 0: // Data
135+
// Once the magic happens..
136+
if(getRecordData(record).equals(magic)){
137+
// Store Magic Address and Break
138+
magicAddress = sectionAddress + getRecordAddress(record);
139+
Log.v(TAG, "Magic Found!");
140+
return true;
141+
}
142+
break;
143+
case 1: // If record type is EOF break the loop
144+
return false;
145+
case 4:
146+
// Recent Section
147+
sectionAddress = Integer.parseInt(getRecordData(record), 16);
148+
break;
149+
}
150+
151+
// Set mark to Magic record -1
152+
reader.mark(BUFFER_LIMIT);
153+
154+
}
155+
} catch (Exception e){
156+
Log.e(TAG, "Find Magic " + e.toString());
157+
}
158+
159+
// If magic is never found and there is no EOF file marker
160+
// Should never return here
161+
return false;
162+
}
163+
164+
/*
165+
Used to get the data address from a record
166+
@param Record as a String
167+
@return Data address as a decimal
168+
*/
169+
private int getRecordAddress(String record){
170+
String hexAddress = record.substring(3,7);
171+
return Integer.parseInt(hexAddress, 16);
172+
}
173+
174+
/*
175+
Used to get the data length from a record
176+
@param Record as a String
177+
@return Data length as a decimal / # of chars
178+
*/
179+
private int getRecordDataLength(String record){
180+
String hexLength = record.substring(1,3);
181+
int len = 2 * Integer.parseInt(hexLength, 16); // Num Of Bytes. Each Byte is represented by 2 chars hence 2*
182+
return len;
183+
}
184+
185+
/*
186+
Used to get the record type from a record
187+
@param Record as a String
188+
@return Record type as a decimal
189+
*/
190+
private int getRecordType(String record){
191+
try {
192+
String hexType = record.substring(7, 9);
193+
return Integer.parseInt(hexType, 16);
194+
} catch (Exception e){
195+
Log.e(TAG, "getRecordType " + e.toString());
196+
return 0;
197+
}
198+
}
199+
200+
/*
201+
Used to get the record type from the current record if it exists
202+
@return Record type as a decimal
203+
*/
204+
public int getRecordType(){
205+
return currentRecordType;
206+
}
207+
208+
/*
209+
Used to get the data from a record
210+
@param Record as a String
211+
@return Data
212+
*/
213+
private String getRecordData(String record){
214+
try {
215+
int len = getRecordDataLength(record);
216+
return record.substring(9, 9 + len);
217+
} catch (Exception e) {
218+
Log.e(TAG, "Get record data " + e.toString());
219+
return "";
220+
}
221+
}
222+
223+
/*
224+
Used to return the data from the next record
225+
*/
226+
public String getNextData() throws IOException {
227+
String data = reader.readLine();
228+
currentRecordType = getRecordType(data);
229+
currentRecordOffset = getRecordAddress(data);
230+
return getRecordData(data);
231+
}
232+
233+
// Specific Functions Used For Partial Flashing Below
234+
/*
235+
Returns the template hash
236+
@return templateHash
237+
*/
238+
public String getTemplateHash(){
239+
return templateHash;
240+
}
241+
242+
/*
243+
Returns the program hash
244+
@return programHash
245+
*/
246+
public String getProgramHash(){
247+
return programHash;
248+
}
249+
250+
/*
251+
Find HEX Meta Data
252+
*/
253+
public Boolean findHexMetaData(String filePath) throws IOException {
254+
255+
}
256+
257+
/*
258+
Find start address & start of PXT data
259+
*/
260+
public Integer getSectionAddress(){
261+
return sectionAddress;
262+
}
263+
264+
/*
265+
Get offset of current record
266+
*/
267+
public int getRecordOffset(){
268+
return currentRecordOffset;
269+
}
270+
271+
public int getRecordOffset(){
272+
return currentRecordOffset;
273+
}
274+
275+
/*
276+
Set mark to beginning of page
277+
*/
278+
public void setMark() throws IOException {
279+
reader.mark(BUFFER_LIMIT);
280+
}
281+
282+
/*
283+
Rewind to start of page
284+
*/
285+
public void rewind() throws IOException {
286+
reader.reset();
287+
}
288+
289+
/*
290+
Number of lines / packets in file
291+
*/
292+
public int numOfLines(String filePath) throws IOException {
293+
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
294+
int lines = 0;
295+
while (!reader.readLine().contains("41140E2FB82FA2B")) lines++;
296+
reader.close();
297+
return lines;
298+
}
299+
300+
/*
301+
Lines / packets before magic
302+
*/
303+
public int getMagicLines()
304+
{
305+
return magicLines;
306+
}
307+
}
308+

0 commit comments

Comments
 (0)