1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-25 22:40:05 +02:00

Amazfit Cor: Untested firmware update support

(refactor stuff along the way)
This commit is contained in:
Andreas Shimokawa 2017-10-24 22:01:25 +02:00
parent e028b4d223
commit 55cdc6d1c5
16 changed files with 416 additions and 199 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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