Support for firmware upgrade/downgrade on Mi 1A.
I hope I didn't break firmware upgrades on some Mi 1 models other than mine (my hardware revision is 2). Upgrades for Mi 1S are currently disabled, we need some brave souls who can help us test this. Closes #173 Also see: #169
This commit is contained in:
parent
6b053c4240
commit
365ce61cb6
|
@ -73,11 +73,8 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".activities.FwAppInstallerActivity"
|
||||
android:label="@string/title_activity_fw_app_insaller">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".activities.ControlCenter" />
|
||||
|
||||
android:label="@string/title_activity_fw_app_insaller"
|
||||
android:parentActivityName=".activities.ControlCenter">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
|
|
@ -25,6 +25,9 @@ public final class MiBandConst {
|
|||
public static final String ORIGIN_K9MAIL = "k9mail";
|
||||
public static final String ORIGIN_PEBBLEMSG = "pebblemsg";
|
||||
public static final String ORIGIN_GENERIC = "generic";
|
||||
public static final String MI_1 = "1";
|
||||
public static final String MI_1A = "1A";
|
||||
public static final String MI_1S = "1S";
|
||||
|
||||
public static int getNotificationPrefIntValue(String pref, String origin, SharedPreferences prefs, int defaultValue) {
|
||||
String key = getNotificationPrefKey(pref, origin);
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
public class MiBandFWHelper {
|
||||
|
@ -21,10 +22,10 @@ public class MiBandFWHelper {
|
|||
private final ContentResolver cr;
|
||||
private byte[] fw;
|
||||
|
||||
private final int firmwareVersionBuild = 1056;
|
||||
private final int firmwareVersionRevision = 1057;
|
||||
private final int firmwareVersionMinor = 1058;
|
||||
private final int firmwareVersionMajor = 1059;
|
||||
private final int offsetFirmwareVersionBuild = 1056;
|
||||
private final int offsetFirmwareVersionRevision = 1057;
|
||||
private final int offsetFirmwareVersionMinor = 1058;
|
||||
private final int offsetFirmwareVersionMajor = 1059;
|
||||
|
||||
/**
|
||||
* Provides a different notification API which is also used on Mi1A devices.
|
||||
|
@ -57,20 +58,38 @@ public class MiBandFWHelper {
|
|||
|
||||
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.");
|
||||
if (fw.length <= offsetFirmwareVersionMajor) {
|
||||
throw new IOException("This doesn't seem to be a Mi Band firmware, file size too small.");
|
||||
}
|
||||
byte firmwareVersionMajor = fw[offsetFirmwareVersionMajor];
|
||||
if (!isSupportedFirmwareVersionMajor(firmwareVersionMajor)) {
|
||||
throw new IOException("Firmware major version not supported, either too new or this isn't a Mi Band firmware: " + firmwareVersionMajor);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw ex; // pass through
|
||||
} catch (Exception e) {
|
||||
throw new IOException("Error reading firmware file: " + uri.toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private byte getFirmwareVersionMajor() {
|
||||
return fw[offsetFirmwareVersionMajor];
|
||||
}
|
||||
|
||||
private byte getFirmwareVersionMinor() {
|
||||
return fw[offsetFirmwareVersionMinor];
|
||||
}
|
||||
|
||||
private boolean isSupportedFirmwareVersionMajor(byte firmwareVersionMajor) {
|
||||
return firmwareVersionMajor == 1 || firmwareVersionMajor == 5;
|
||||
}
|
||||
|
||||
public int getFirmwareVersion() {
|
||||
return (fw[firmwareVersionMajor] << 24) | (fw[firmwareVersionMinor] << 16) | (fw[firmwareVersionRevision] << 8) | fw[firmwareVersionBuild];
|
||||
return (fw[offsetFirmwareVersionMajor] << 24) | (fw[offsetFirmwareVersionMinor] << 16) | (fw[offsetFirmwareVersionRevision] << 8) | fw[offsetFirmwareVersionBuild];
|
||||
}
|
||||
|
||||
public String getHumanFirmwareVersion() {
|
||||
return String.format(Locale.US, "%d.%d.%d.%d", fw[firmwareVersionMajor], fw[firmwareVersionMinor], fw[firmwareVersionRevision], fw[firmwareVersionBuild]);
|
||||
return String.format(Locale.US, "%d.%d.%d.%d", fw[offsetFirmwareVersionMajor], fw[offsetFirmwareVersionMinor], fw[offsetFirmwareVersionRevision], fw[offsetFirmwareVersionBuild]);
|
||||
}
|
||||
|
||||
public byte[] getFw() {
|
||||
|
@ -85,4 +104,15 @@ public class MiBandFWHelper {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
|
||||
String deviceHW = device.getHardwareVersion();
|
||||
if (MiBandConst.MI_1.equals(deviceHW)) {
|
||||
return getFirmwareVersionMajor() == 1;
|
||||
}
|
||||
if (MiBandConst.MI_1A.equals(deviceHW)) {
|
||||
return getFirmwareVersionMajor() == 5;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@ public class MiBandFWInstallHandler implements InstallHandler {
|
|||
GenericItem fwItem = new GenericItem(mContext.getString(R.string.miband_installhandler_miband_firmware, helper.getHumanFirmwareVersion()));
|
||||
fwItem.setIcon(R.drawable.ic_device_miband);
|
||||
|
||||
if (!helper.isFirmwareGenerallyCompatibleWith(device)) {
|
||||
fwItem.setDetails(mContext.getString(R.string.miband_fwinstaller_incompatible_version));
|
||||
installActivity.setInfoText(mContext.getString(R.string.fwinstaller_firmware_not_compatible_to_device));
|
||||
installActivity.setInstallEnabled(false);
|
||||
return;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder(mContext.getString(R.string.fw_upgrade_notice, helper.getHumanFirmwareVersion()));
|
||||
|
||||
if (helper.isFirmwareWhitelisted()) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.miband;
|
|||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
|
||||
|
||||
public class DeviceInfo extends AbstractInfo {
|
||||
|
@ -75,8 +76,28 @@ public class DeviceInfo extends AbstractInfo {
|
|||
'}';
|
||||
}
|
||||
|
||||
public boolean isMili1() {
|
||||
return hwVersion == 2;
|
||||
}
|
||||
|
||||
public boolean isMili1A() {
|
||||
return feature == 5 && appearance == 0 || feature == 0 && hwVersion == 208;
|
||||
}
|
||||
|
||||
public boolean isMilli1S() {
|
||||
return false; // FIXME: what to do here?
|
||||
}
|
||||
|
||||
public String getHwVersion() {
|
||||
if (isMili1()) {
|
||||
return MiBandConst.MI_1;
|
||||
}
|
||||
if (isMili1A()) {
|
||||
return MiBandConst.MI_1A;
|
||||
}
|
||||
if (isMilli1S()) {
|
||||
return MiBandConst.MI_1S;
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -687,16 +687,17 @@ public class MiBandSupport extends AbstractBTLEDeviceSupport {
|
|||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
mDeviceInfo = new DeviceInfo(value);
|
||||
LOG.warn("Device info: " + mDeviceInfo);
|
||||
versionCmd.hwVersion = mDeviceInfo.getHwVersion();
|
||||
versionCmd.fwVersion = mDeviceInfo.getHumanFirmwareVersion();
|
||||
handleGBDeviceEvent(versionCmd);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDeviceName(byte[] value, int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
versionCmd.hwVersion = new String(value);
|
||||
handleGBDeviceEvent(versionCmd);
|
||||
}
|
||||
// if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
// versionCmd.hwVersion = new String(value);
|
||||
// handleGBDeviceEvent(versionCmd);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,7 +15,6 @@ import java.util.UUID;
|
|||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
|
@ -38,9 +37,6 @@ public class UpdateFirmwareOperation extends AbstractMiBandOperation {
|
|||
|
||||
@Override
|
||||
protected void doPerform() throws IOException {
|
||||
if (getSupport().getDeviceInfo().isMili1A()) {
|
||||
throw new IOException("Firmware update is not supported for the Mi Band 1A, yet.");
|
||||
}
|
||||
MiBandFWHelper mFwHelper = new MiBandFWHelper(uri, getContext());
|
||||
String mMac = getDevice().getAddress();
|
||||
String[] mMacOctets = mMac.split(":");
|
||||
|
|
|
@ -210,4 +210,6 @@
|
|||
<string name="device_not_connected">Not connected.</string>
|
||||
<string name="user_feedback_all_alarms_disabled">All alarms disabled</string>
|
||||
<string name="pref_title_keep_data_on_device">Keep activity data on device</string>
|
||||
<string name="miband_fwinstaller_incompatible_version">Incompatible firmware</string>
|
||||
<string name="fwinstaller_firmware_not_compatible_to_device">This firmware is not compatible with the device</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue