mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-08-26 09:11:37 +02:00
Make firmware reading a bit more failsafe #30
This commit is contained in:
parent
bdc9e70e6e
commit
910d9ef398
@ -8,9 +8,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
public class MiBandFWHelper {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MiBandFWHelper.class);
|
||||
|
||||
@ -29,41 +32,25 @@ public class MiBandFWHelper {
|
||||
16779568 //1.0.9.48 tested by developer
|
||||
};
|
||||
|
||||
public MiBandFWHelper(Uri uri, Context context) {
|
||||
public MiBandFWHelper(Uri uri, Context context) throws IOException {
|
||||
this.uri = uri;
|
||||
cr = context.getContentResolver();
|
||||
|
||||
InputStream fin;
|
||||
|
||||
try {
|
||||
fin = new BufferedInputStream(cr.openInputStream(uri));
|
||||
this.fw = new byte[fin.available()];
|
||||
fin.read(fw);
|
||||
fin.close();
|
||||
|
||||
try (InputStream in = new BufferedInputStream(cr.openInputStream(uri))){
|
||||
this.fw = FileUtils.readAll(in, 1024 * 1024); // 1 MB
|
||||
if (fw.length > firmwareVersionMajor && fw[firmwareVersionMajor] != 1) {
|
||||
throw new IOException("Firmware major version should be 1, probably this isn't a MiBand firmware.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
this.fw = null;
|
||||
throw new IOException("Error reading firmware file: " + uri.toString(), e);
|
||||
}
|
||||
|
||||
if (fw[firmwareVersionMajor] != 1) {
|
||||
LOG.error("Firmware major version should be 1, probably this isn't a MiBand firmware.");
|
||||
this.fw = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public int getFirmwareVersion() {
|
||||
if (fw == null) {
|
||||
return -1;
|
||||
}
|
||||
return (fw[firmwareVersionMajor] << 24) | (fw[firmwareVersionMinor] << 16) | (fw[firmwareVersionRevision] << 8) | fw[firmwareVersionBuild];
|
||||
}
|
||||
|
||||
public String getHumanFirmwareVersion() {
|
||||
if (fw == null) {
|
||||
return "UNK";
|
||||
}
|
||||
return String.format(Locale.US, "%d.%d.%d.%d", fw[firmwareVersionMajor], fw[firmwareVersionMinor], fw[firmwareVersionRevision], fw[firmwareVersionBuild]);
|
||||
}
|
||||
|
||||
@ -94,5 +81,4 @@ public class MiBandFWHelper {
|
||||
crc &= 0xffff;
|
||||
return crc;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -592,21 +592,23 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
||||
|
||||
@Override
|
||||
public void onInstallApp(Uri uri) {
|
||||
MiBandFWHelper mFwHelper = new MiBandFWHelper(uri, getContext());
|
||||
String mMac = getDevice().getAddress();
|
||||
String[] mMacOctets = mMac.split(":");
|
||||
try {
|
||||
MiBandFWHelper mFwHelper = new MiBandFWHelper(uri, getContext());
|
||||
String mMac = getDevice().getAddress();
|
||||
String[] mMacOctets = mMac.split(":");
|
||||
|
||||
int newFwVersion = mFwHelper.getFirmwareVersion();
|
||||
int oldFwVersion = mDeviceInfo.getFirmwareVersion();
|
||||
int checksum = (Integer.decode("0x" + mMacOctets[4]) << 8 | Integer.decode("0x" + mMacOctets[5])) ^ mFwHelper.getCRC16(mFwHelper.getFw());
|
||||
int newFwVersion = mFwHelper.getFirmwareVersion();
|
||||
int oldFwVersion = mDeviceInfo.getFirmwareVersion();
|
||||
int checksum = (Integer.decode("0x" + mMacOctets[4]) << 8 | Integer.decode("0x" + mMacOctets[5])) ^ mFwHelper.getCRC16(mFwHelper.getFw());
|
||||
|
||||
if (sendFirmwareInfo(oldFwVersion, newFwVersion, mFwHelper.getFw().length, checksum)) {
|
||||
firmwareInfoSent = true;
|
||||
newFirmware = mFwHelper.getFw();
|
||||
//the firmware will be sent by the notification listener if the band confirms that the metadata are ok.
|
||||
if (sendFirmwareInfo(oldFwVersion, newFwVersion, mFwHelper.getFw().length, checksum)) {
|
||||
firmwareInfoSent = true;
|
||||
newFirmware = mFwHelper.getFw();
|
||||
//the firmware will be sent by the notification listener if the band confirms that the metadata are ok.
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
GB.toast(getContext(), "Firmware cannot be installed: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,11 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
@ -44,4 +46,27 @@ public class FileUtils {
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the given InputStream into a byte array, but does not
|
||||
* read more than maxLen bytes.
|
||||
* @param in the stream to read from
|
||||
* @param maxLen the maximum number of bytes to read/return
|
||||
* @return the bytes read from the InputStream
|
||||
* @throws IOException when reading failed or when maxLen was exceeded
|
||||
*/
|
||||
public static byte[] readAll(InputStream in, long maxLen) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max(8192, in.available()));
|
||||
byte[] buf = new byte[8192];
|
||||
int read = 0;
|
||||
long totalRead = 0;
|
||||
while ((read = in.read(buf)) > 0) {
|
||||
out.write(buf, 0, read);
|
||||
totalRead += read;
|
||||
if (totalRead > maxLen) {
|
||||
throw new IOException("Too much data to read into memory. Got already " + totalRead + buf);
|
||||
}
|
||||
}
|
||||
return out.toByteArray();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user