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
here
cpfeiffer 2015-12-07 01:11:07 +01:00
parent 6b053c4240
commit 365ce61cb6
8 changed files with 77 additions and 21 deletions

View File

@ -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" />

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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()) {

View File

@ -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 "?";
}
}

View File

@ -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);
// }
}
/**

View File

@ -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(":");

View File

@ -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>