mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-04 01:09:47 +01:00
Amazfit Cor: Untested firmware update support
(refactor stuff along the way)
This commit is contained in:
parent
e028b4d223
commit
55cdc6d1c5
@ -0,0 +1,79 @@
|
||||
/* Copyright (C) 2016-2017 Carsten Pfeiffer
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
|
||||
|
||||
public abstract class HuamiFWHelper extends AbstractMiBandFWHelper {
|
||||
protected HuamiFirmwareInfo firmwareInfo;
|
||||
|
||||
public HuamiFWHelper(Uri uri, Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(int version) {
|
||||
return firmwareInfo.toVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmwareVersion() {
|
||||
return firmwareInfo.getFirmwareVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmware2Version() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHumanFirmwareVersion2() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getWhitelistedFirmwareVersions() {
|
||||
return firmwareInfo.getWhitelistedVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
|
||||
return firmwareInfo.isGenerallyCompatibleWith(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFirmware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
firmwareInfo.checkValid();
|
||||
}
|
||||
|
||||
public HuamiFirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
}
|
@ -22,53 +22,15 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipFirmwareInfo;
|
||||
|
||||
public class AmazfitBipFWHelper extends AbstractMiBandFWHelper {
|
||||
public class AmazfitBipFWHelper extends HuamiFWHelper {
|
||||
|
||||
public AmazfitBipFWHelper(Uri uri, Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
private AmazfitBipFirmwareInfo firmwareInfo;
|
||||
|
||||
@Override
|
||||
public String format(int version) {
|
||||
return AmazfitBipFirmwareInfo.toVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmwareVersion() {
|
||||
return firmwareInfo.getFirmwareVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmware2Version() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHumanFirmwareVersion2() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getWhitelistedFirmwareVersions() {
|
||||
return AmazfitBipFirmwareInfo.getWhitelistedVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
|
||||
return firmwareInfo.isGenerallyCompatibleWith(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFirmware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) {
|
||||
@ -77,14 +39,4 @@ public class AmazfitBipFWHelper extends AbstractMiBandFWHelper {
|
||||
throw new IllegalArgumentException("Not a an Amazifit Bip firmware");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
firmwareInfo.checkValid();
|
||||
}
|
||||
|
||||
public AmazfitBipFirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ public class AmazfitCorCoordinator extends HuamiCoordinator {
|
||||
|
||||
@Override
|
||||
public InstallHandler findInstallHandler(Uri uri, Context context) {
|
||||
return null;
|
||||
AmazfitCorFWInstallHandler handler = new AmazfitCorFWInstallHandler(uri, context);
|
||||
return handler.isValid() ? handler : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,43 @@
|
||||
/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipFirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor.AmazfitCorFirmwareInfo;
|
||||
|
||||
public class AmazfitCorFWHelper extends HuamiFWHelper {
|
||||
|
||||
public AmazfitCorFWHelper(Uri uri, Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) {
|
||||
firmwareInfo = new AmazfitCorFirmwareInfo(wholeFirmwareBytes);
|
||||
if (!firmwareInfo.isHeaderValid()) {
|
||||
throw new IllegalArgumentException("Not a an Amazifit Bip firmware");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2015-2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWInstallHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
|
||||
|
||||
class AmazfitCorFWInstallHandler extends AbstractMiBandFWInstallHandler {
|
||||
AmazfitCorFWInstallHandler(Uri uri, Context context) {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GenericItem createInstallItem() {
|
||||
return new GenericItem(mContext.getString(R.string.amazfitcor_firmware, helper.getHumanFirmwareVersion()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFwUpgradeNotice() {
|
||||
return mContext.getString(R.string.fw_upgrade_notice_amazfitcor, helper.getHumanFirmwareVersion());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractMiBandFWHelper createHelper(Uri uri, Context context) throws IOException {
|
||||
return new AmazfitBipFWHelper(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSupportedDeviceType(GBDevice device) {
|
||||
return device.getType() == DeviceType.AMAZFITCOR;
|
||||
}
|
||||
}
|
@ -22,52 +22,15 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.AbstractMiBandFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo;
|
||||
|
||||
public class MiBand2FWHelper extends AbstractMiBandFWHelper {
|
||||
private Mi2FirmwareInfo firmwareInfo;
|
||||
public class MiBand2FWHelper extends HuamiFWHelper {
|
||||
|
||||
public MiBand2FWHelper(Uri uri, Context context) throws IOException {
|
||||
super(uri, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(int version) {
|
||||
return Mi2FirmwareInfo.toVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmwareVersion() {
|
||||
return firmwareInfo.getFirmwareVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFirmware2Version() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHumanFirmwareVersion2() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int[] getWhitelistedFirmwareVersions() {
|
||||
return Mi2FirmwareInfo.getWhitelistedVersions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFirmwareGenerallyCompatibleWith(GBDevice device) {
|
||||
return firmwareInfo.isGenerallyCompatibleWith(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFirmware() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected void determineFirmwareInfo(byte[] wholeFirmwareBytes) {
|
||||
@ -76,14 +39,4 @@ public class MiBand2FWHelper extends AbstractMiBandFWHelper {
|
||||
throw new IllegalArgumentException("Not a Mi Band 2 firmware");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
firmwareInfo.checkValid();
|
||||
}
|
||||
|
||||
public Mi2FirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor.AmazfitCorSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.liveview.LiveviewSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipSupport;
|
||||
@ -114,9 +115,11 @@ public class DeviceSupportFactory {
|
||||
deviceSupport = new ServiceDeviceSupport(new MiBand2Support(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
case AMAZFITBIP:
|
||||
case AMAZFITCOR:
|
||||
deviceSupport = new ServiceDeviceSupport(new AmazfitBipSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
case AMAZFITCOR:
|
||||
deviceSupport = new ServiceDeviceSupport(new AmazfitCorSupport(), EnumSet.of(ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
case VIBRATISSIMO:
|
||||
deviceSupport = new ServiceDeviceSupport(new VibratissimoSupport(), EnumSet.of(ServiceDeviceSupport.Flags.THROTTLING, ServiceDeviceSupport.Flags.BUSY_CHECKING));
|
||||
break;
|
||||
|
@ -16,13 +16,16 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
|
||||
public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
public class AmazfitBipFirmwareInfo extends HuamiFirmwareInfo {
|
||||
// total crap maybe
|
||||
private static final byte[] GPS_HEADER = new byte[]{
|
||||
(byte) 0xcb, 0x51, (byte) 0xc1, 0x30, 0x41, (byte) 0x9e, 0x5e, (byte) 0xd3,
|
||||
@ -37,10 +40,6 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
|
||||
private static final int FW_HEADER_OFFSET = 0x9330;
|
||||
|
||||
private static final byte[] RES_HEADER = new byte[]{ // HMRES resources file (*.res)
|
||||
0x48, 0x4d, 0x52, 0x45, 0x53
|
||||
};
|
||||
|
||||
private static final byte[] GPS_ALMANAC_HEADER = new byte[]{ // probably wrong
|
||||
(byte) 0xa0, (byte) 0x80, 0x08, 0x00, (byte) 0x8b, 0x07
|
||||
};
|
||||
@ -49,6 +48,7 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
0x2a, 0x12, (byte) 0xa0, 0x02
|
||||
};
|
||||
|
||||
private static Map<Integer, String> crcToVersion = new HashMap<>();
|
||||
static {
|
||||
// firmware
|
||||
crcToVersion.put(25257, "0.0.8.74");
|
||||
@ -75,6 +75,9 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
@Override
|
||||
protected HuamiFirmwareType determineFirmwareType(byte[] bytes) {
|
||||
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
|
||||
if (bytes.length > 500000) { // dont know how to distinguish from Cor .res
|
||||
return HuamiFirmwareType.INVALID;
|
||||
}
|
||||
return HuamiFirmwareType.RES;
|
||||
}
|
||||
if (ArrayUtils.startsWith(bytes, GPS_HEADER)) {
|
||||
@ -98,4 +101,8 @@ public class AmazfitBipFirmwareInfo extends Mi2FirmwareInfo {
|
||||
return isHeaderValid() && device.getType() == DeviceType.AMAZFITBIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Integer, String> getCrcMap() {
|
||||
return crcToVersion;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip;
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -31,10 +31,11 @@ import java.util.Locale;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiWeatherConditions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiIcon;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||
@ -44,10 +45,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotificat
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.AlertNotificationProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.profiles.alertnotification.NewAlert;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipFetchLogsOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations.AmazfitBipUpdateFirmwareOperation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiIcon;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.NotificationStrategy;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.MiBand2Support;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.StringUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.Version;
|
||||
|
||||
@ -120,15 +120,6 @@ public class AmazfitBipSupport extends MiBand2Support {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInstallApp(Uri uri) {
|
||||
try {
|
||||
new AmazfitBipUpdateFirmwareOperation(uri, this).perform();
|
||||
} catch (IOException ex) {
|
||||
GB.toast(getContext(), "Firmware cannot be installed: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendWeather(WeatherSpec weatherSpec) {
|
||||
if (gbDevice.getFirmwareVersion() == null) {
|
||||
@ -258,4 +249,9 @@ public class AmazfitBipSupport extends MiBand2Support {
|
||||
setLanguage(builder);
|
||||
requestGPSVersion(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException {
|
||||
return new AmazfitBipFWHelper(uri, context);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,100 @@
|
||||
/* Copyright (C) 2016-2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
|
||||
|
||||
|
||||
public abstract class HuamiFirmwareInfo {
|
||||
|
||||
protected static final byte[] RES_HEADER = new byte[]{ // HMRES resources file (*.res)
|
||||
0x48, 0x4d, 0x52, 0x45, 0x53
|
||||
};
|
||||
|
||||
protected static final byte[] FT_HEADER = new byte[]{ // HMZK font file (*.ft, *.ft.xx)
|
||||
0x48,
|
||||
0x4d,
|
||||
0x5a,
|
||||
0x4b
|
||||
};
|
||||
|
||||
private HuamiFirmwareType firmwareType = HuamiFirmwareType.FIRMWARE;
|
||||
|
||||
public String toVersion(int crc16) {
|
||||
return getCrcMap().get(crc16);
|
||||
}
|
||||
|
||||
public int[] getWhitelistedVersions() {
|
||||
return ArrayUtils.toIntArray(getCrcMap().keySet());
|
||||
}
|
||||
|
||||
private final int crc16;
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
private String firmwareVersion;
|
||||
|
||||
public HuamiFirmwareInfo(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
crc16 = CheckSums.getCRC16(bytes);
|
||||
firmwareVersion = getCrcMap().get(crc16);
|
||||
firmwareType = determineFirmwareType(bytes);
|
||||
}
|
||||
|
||||
public abstract boolean isGenerallyCompatibleWith(GBDevice device);
|
||||
|
||||
public boolean isHeaderValid() {
|
||||
return getFirmwareType() != HuamiFirmwareType.INVALID;
|
||||
}
|
||||
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the firmware in number of bytes.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getSize() {
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public int getCrc16() {
|
||||
return crc16;
|
||||
}
|
||||
|
||||
public int getFirmwareVersion() {
|
||||
return getCrc16(); // HACK until we know how to determine the version from the fw bytes
|
||||
}
|
||||
|
||||
public HuamiFirmwareType getFirmwareType() {
|
||||
return firmwareType;
|
||||
}
|
||||
|
||||
protected abstract Map<Integer, String> getCrcMap();
|
||||
|
||||
protected abstract HuamiFirmwareType determineFirmwareType(byte[] bytes);
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/* Copyright (C) 2017 Andreas Shimokawa
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
|
||||
public class AmazfitCorFirmwareInfo extends HuamiFirmwareInfo {
|
||||
// guessed - at least it is the same accross current versions and different from other devices
|
||||
private static final byte[] FW_HEADER = new byte[]{
|
||||
(byte) 0x06, (byte) 0x48, (byte) 0x00, (byte) 0x47, (byte) 0xfe, (byte) 0xe7, (byte) 0xfe, (byte) 0xe7,
|
||||
(byte) 0xfe, (byte) 0xe7, (byte) 0xfe, (byte) 0xe7, (byte) 0xfe, (byte) 0xe7, (byte) 0xfe, (byte) 0xe7
|
||||
};
|
||||
|
||||
private static final int FW_HEADER_OFFSET = 0x9330;
|
||||
|
||||
private static Map<Integer, String> crcToVersion = new HashMap<>();
|
||||
|
||||
static {
|
||||
// firmware
|
||||
crcToVersion.put(39948, "1.0.5.60");
|
||||
|
||||
// resources
|
||||
crcToVersion.put(46341, "RES 1.0.5.60");
|
||||
}
|
||||
|
||||
public AmazfitCorFirmwareInfo(byte[] bytes) {
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HuamiFirmwareType determineFirmwareType(byte[] bytes) {
|
||||
if (ArrayUtils.startsWith(bytes, RES_HEADER)) {
|
||||
if (bytes.length < 700000) { // dont know how to distinguish from Bip .res
|
||||
return HuamiFirmwareType.INVALID;
|
||||
}
|
||||
return HuamiFirmwareType.RES;
|
||||
} else if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET)) {
|
||||
// TODO: this is certainly not a correct validation, but it works for now
|
||||
return HuamiFirmwareType.FIRMWARE;
|
||||
}
|
||||
return HuamiFirmwareType.INVALID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerallyCompatibleWith(GBDevice device) {
|
||||
return isHeaderValid() && device.getType() == DeviceType.AMAZFITCOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<Integer, String> getCrcMap() {
|
||||
return crcToVersion;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2017 Andreas Shimokawa, Carsten Pfeiffer
|
||||
/* Copyright (C) 2017 Andreas Shimokawa
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
@ -14,26 +14,21 @@
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.operations;
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.huami.amazfitcor;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitbip.AmazfitBipFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.amazfitcor.AmazfitCorFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.amazfitbip.AmazfitBipSupport;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.operations.UpdateFirmwareOperation;
|
||||
|
||||
public class AmazfitBipUpdateFirmwareOperation extends UpdateFirmwareOperation {
|
||||
public AmazfitBipUpdateFirmwareOperation(Uri uri, AmazfitBipSupport support) {
|
||||
super(uri, support);
|
||||
}
|
||||
public class AmazfitCorSupport extends AmazfitBipSupport {
|
||||
|
||||
|
||||
protected Mi2FirmwareInfo createFwInfo(Uri uri, Context context) throws IOException {
|
||||
AmazfitBipFWHelper fwHelper = new AmazfitBipFWHelper(uri, getContext());
|
||||
return fwHelper.getFirmwareInfo();
|
||||
@Override
|
||||
public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException {
|
||||
return new AmazfitCorFWHelper(uri, context);
|
||||
}
|
||||
}
|
@ -21,11 +21,11 @@ import java.util.Map;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.CheckSums;
|
||||
|
||||
public class Mi2FirmwareInfo {
|
||||
public class Mi2FirmwareInfo extends HuamiFirmwareInfo {
|
||||
private static final byte[] FW_HEADER = new byte[]{
|
||||
(byte) 0xa3,
|
||||
(byte) 0x68,
|
||||
@ -47,13 +47,6 @@ public class Mi2FirmwareInfo {
|
||||
|
||||
private static final int FW_HEADER_OFFSET = 0x150;
|
||||
|
||||
private static final byte[] FT_HEADER = new byte[] { // HMZK font file (*.ft, *.ft.xx)
|
||||
0x48,
|
||||
0x4d,
|
||||
0x5a,
|
||||
0x4b
|
||||
};
|
||||
|
||||
protected static Map<Integer,String> crcToVersion = new HashMap<>();
|
||||
static {
|
||||
// firmware
|
||||
@ -68,30 +61,12 @@ public class Mi2FirmwareInfo {
|
||||
crcToVersion.put(6377, "Font (En)");
|
||||
}
|
||||
|
||||
private HuamiFirmwareType firmwareType = HuamiFirmwareType.FIRMWARE;
|
||||
|
||||
public static String toVersion(int crc16) {
|
||||
return crcToVersion.get(crc16);
|
||||
}
|
||||
|
||||
public static int[] getWhitelistedVersions() {
|
||||
return ArrayUtils.toIntArray(crcToVersion.keySet());
|
||||
}
|
||||
|
||||
private final int crc16;
|
||||
|
||||
private byte[] bytes;
|
||||
private String firmwareVersion;
|
||||
|
||||
public Mi2FirmwareInfo(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
crc16 = CheckSums.getCRC16(bytes);
|
||||
firmwareVersion = crcToVersion.get(crc16);
|
||||
firmwareType = determineFirmwareType(bytes);
|
||||
super(bytes);
|
||||
}
|
||||
|
||||
protected HuamiFirmwareType determineFirmwareType(byte[] bytes) {
|
||||
if (ArrayUtils.startsWith(bytes, FT_HEADER)) {
|
||||
if (ArrayUtils.startsWith(bytes, HuamiFirmwareInfo.FT_HEADER)) {
|
||||
return HuamiFirmwareType.FONT;
|
||||
}
|
||||
if (ArrayUtils.equals(bytes, FW_HEADER, FW_HEADER_OFFSET)) {
|
||||
@ -105,34 +80,7 @@ public class Mi2FirmwareInfo {
|
||||
return isHeaderValid() && device.getType() == DeviceType.MIBAND2;
|
||||
}
|
||||
|
||||
public boolean isHeaderValid() {
|
||||
return getFirmwareType() != HuamiFirmwareType.INVALID;
|
||||
}
|
||||
|
||||
public void checkValid() throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the firmware in number of bytes.
|
||||
* @return
|
||||
*/
|
||||
public int getSize() {
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public int getCrc16() {
|
||||
return crc16;
|
||||
}
|
||||
|
||||
public int getFirmwareVersion() {
|
||||
return getCrc16(); // HACK until we know how to determine the version from the fw bytes
|
||||
}
|
||||
|
||||
public HuamiFirmwareType getFirmwareType() {
|
||||
return firmwareType;
|
||||
protected Map<Integer, String> getCrcMap() {
|
||||
return crcToVersion;
|
||||
}
|
||||
}
|
||||
|
@ -55,9 +55,11 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInf
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventCallControl;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2FWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.DateTimeDisplay;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.DoNotDisturb;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
|
||||
@ -1539,4 +1541,8 @@ public class MiBand2Support extends AbstractBTLEDeviceSupport {
|
||||
setInactivityWarnings(builder);
|
||||
setHeartrateSleepSupport(builder);
|
||||
}
|
||||
|
||||
public HuamiFWHelper createFWHelper(Uri uri, Context context) throws IOException {
|
||||
return new MiBand2FWHelper(uri, context);
|
||||
}
|
||||
}
|
||||
|
@ -32,12 +32,14 @@ import java.util.UUID;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventDisplayMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiFWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.miband2.MiBand2FWHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetProgressAction;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.AbstractMiBand2Operation;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.huami.HuamiFirmwareType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.miband2.Mi2FirmwareInfo;
|
||||
@ -52,7 +54,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
||||
protected final BluetoothGattCharacteristic fwCControlChar;
|
||||
protected final BluetoothGattCharacteristic fwCDataChar;
|
||||
protected final Prefs prefs = GBApplication.getPrefs();
|
||||
protected Mi2FirmwareInfo firmwareInfo;
|
||||
protected HuamiFirmwareInfo firmwareInfo;
|
||||
|
||||
public UpdateFirmwareOperation(Uri uri, MiBand2Support support) {
|
||||
super(support);
|
||||
@ -80,8 +82,8 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
||||
//the firmware will be sent by the notification listener if the band confirms that the metadata are ok.
|
||||
}
|
||||
|
||||
protected Mi2FirmwareInfo createFwInfo(Uri uri, Context context) throws IOException {
|
||||
MiBand2FWHelper fwHelper = new MiBand2FWHelper(uri, context);
|
||||
protected HuamiFirmwareInfo createFwInfo(Uri uri, Context context) throws IOException {
|
||||
HuamiFWHelper fwHelper = getSupport().createFWHelper(uri, context);
|
||||
return fwHelper.getFirmwareInfo();
|
||||
}
|
||||
|
||||
@ -229,7 +231,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
||||
* @return whether the transfer succeeded or not. Only a BT layer exception will cause the transmission to fail.
|
||||
* @see #handleNotificationNotif
|
||||
*/
|
||||
private boolean sendFirmwareData(Mi2FirmwareInfo info) {
|
||||
private boolean sendFirmwareData(HuamiFirmwareInfo info) {
|
||||
byte[] fwbytes = info.getBytes();
|
||||
int len = fwbytes.length;
|
||||
final int packetLength = 20;
|
||||
@ -276,7 +278,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
||||
}
|
||||
|
||||
|
||||
private void sendChecksum(Mi2FirmwareInfo firmwareInfo) throws IOException {
|
||||
private void sendChecksum(HuamiFirmwareInfo firmwareInfo) throws IOException {
|
||||
TransactionBuilder builder = performInitialized("send firmware checksum");
|
||||
int crc16 = firmwareInfo.getCrc16();
|
||||
byte[] bytes = BLETypeConversions.fromUint16(crc16);
|
||||
@ -288,7 +290,7 @@ public class UpdateFirmwareOperation extends AbstractMiBand2Operation {
|
||||
builder.queue(getQueue());
|
||||
}
|
||||
|
||||
private Mi2FirmwareInfo getFirmwareInfo() {
|
||||
private HuamiFirmwareInfo getFirmwareInfo() {
|
||||
return firmwareInfo;
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@
|
||||
<string name="title_activity_fw_app_insaller">FW/App installer</string>
|
||||
<string name="fw_upgrade_notice">You are about to install firmware %s instead of the one currently on your Mi Band.</string>
|
||||
<string name="fw_upgrade_notice_amazfitbip">You are about to install firmware %s instead of the one currently on your Amazfit Bip.\n\nPlease make sure to install the .gps firmware, then the .res file, and finally the .fw file. Your watch will reboot after installing the .fw file.\n\nNote: You do not have to install .res and .gps if these files are exactly the same as the ones previously installed.\n\nEXPERIMENTAL, PROCEED AT YOUR OWN RISK</string>
|
||||
<string name="fw_upgrade_notice_amazfitcor">You are about to install firmware %s instead of the one currently on your Amazfit Cor.\n\nPlease make sure to install the .res file, and after that the .fw file. Your watch will reboot after installing the .fw file.\n\nNote: You do not have to install .res if it is exactly the same as the one previously installed.\n\nEXPERIMENTAL, PROCEED AT YOUR OWN RISK</string>
|
||||
<string name="fw_multi_upgrade_notice">You are about to install firmwares %1$s and %2$s instead of the ones currently on your Mi Band.</string>
|
||||
<string name="miband_firmware_known">This firmware has been tested and is known to be compatible with Gadgetbridge.</string>
|
||||
<string name="miband_firmware_unknown_warning">"This firmware is untested and may not be compatible with Gadgetbridge.\n\nYou are NOT encouraged to flash it to your Mi Band!"</string>
|
||||
@ -308,6 +309,7 @@
|
||||
<string name="fwapp_install_device_not_ready">File cannot be installed, device not ready.</string>
|
||||
<string name="miband_installhandler_miband_firmware">Mi Band Firmware %1$s</string>
|
||||
<string name="amazfitbip_firmware">Amazfit Bip Firmware %1$s</string>
|
||||
<string name="amazfitcor_firmware">Amazfit Cor Firmware %1$s</string>
|
||||
<string name="miband_fwinstaller_compatible_version">Compatible version</string>
|
||||
<string name="miband_fwinstaller_untested_version">Untested version!</string>
|
||||
<string name="fwappinstaller_connection_state">Connection to device: %1$s</string>
|
||||
|
Loading…
Reference in New Issue
Block a user