diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java index aed780d25..1b815f5e8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/adapter/fossil_hr/FossilHRWatchAdapter.java @@ -64,7 +64,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.parser.Activ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.RequestMtuRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayCallNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayTextNotificationRequest; @@ -548,9 +548,9 @@ public class FossilHRWatchAdapter extends FossilWatchAdapter { } }); }else{ - queueWrite(new FileGetRequest(handle, this) { + queueWrite(new FileGetRawRequest(handle, this) { @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { logger.debug("downloaded regular file"); handleFileDownload(handle, fileData); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/button/ButtonConfigurationGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/button/ButtonConfigurationGetRequest.java index 571f1a65e..9604f1463 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/button/ButtonConfigurationGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/button/ButtonConfigurationGetRequest.java @@ -22,15 +22,15 @@ import java.nio.ByteOrder; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.buttonconfig.ConfigPayload; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; -public class ButtonConfigurationGetRequest extends FileGetRequest { +public class ButtonConfigurationGetRequest extends FileGetRawRequest { public ButtonConfigurationGetRequest(FossilWatchAdapter adapter) { super(FileHandle.SETTINGS_BUTTONS, adapter); } @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { log("fileData"); ByteBuffer buffer = ByteBuffer.wrap(fileData); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java index 9df83d1b0..65dc832ab 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/configuration/ConfigurationGetRequest.java @@ -21,16 +21,15 @@ import nodomain.freeyourgadget.gadgetbridge.model.GenericItem; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupAndGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; -public class ConfigurationGetRequest extends FileGetRequest { +public class ConfigurationGetRequest extends FileGetRawRequest { public ConfigurationGetRequest(FossilWatchAdapter adapter) { super(FileHandle.CONFIGURATION, adapter); } @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { byte[] data = new byte[fileData.length - 12 - 4]; System.arraycopy(fileData, 12, data, 0, data.length); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/device_info/GetDeviceInfoRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/device_info/GetDeviceInfoRequest.java index 76a9bf864..a66da4b05 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/device_info/GetDeviceInfoRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/device_info/GetDeviceInfoRequest.java @@ -3,13 +3,12 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fo import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicReferenceArray; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; -public class GetDeviceInfoRequest extends FileGetRequest { +public class GetDeviceInfoRequest extends FileGetRawRequest { enum INFO_CLASS{ SUPPORTED_FILE_VERSIONS((short) 0x0a, SupportedFileVersionsInfo.class), ; @@ -42,7 +41,7 @@ public class GetDeviceInfoRequest extends FileGetRequest { } @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { ByteBuffer buffer = ByteBuffer.wrap(fileData); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.position(12); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRawRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRawRequest.java new file mode 100644 index 000000000..055b6c5d1 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRawRequest.java @@ -0,0 +1,136 @@ +/* Copyright (C) 2019-2020 Daniel Dakhno + + 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 . */ +package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file; + +import android.bluetooth.BluetoothGattCharacteristic; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.UUID; +import java.util.zip.CRC32; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.ResultCode; + +public abstract class FileGetRawRequest extends FossilRequest { + private short handle; + private FossilWatchAdapter adapter; + + private ByteBuffer fileBuffer; + + private byte[] fileData; + + private boolean finished = false; + + public FileGetRawRequest(short handle, FossilWatchAdapter adapter) { + this.handle = handle; + this.adapter = adapter; + + this.data = + createBuffer() + .putShort(handle) + .putInt(0) + .putInt(0xFFFFFFFF) + .array(); + } + + public FileGetRawRequest(FileHandle handle, FossilWatchAdapter adapter){ + this(handle.getHandle(), adapter); + } + + public FossilWatchAdapter getAdapter() { + return adapter; + } + + @Override + public boolean isFinished(){ + return finished; + } + + @Override + public void handleResponse(BluetoothGattCharacteristic characteristic) { + byte[] value = characteristic.getValue(); + byte first = value[0]; + if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")){ + if((first & 0x0F) == 1){ + ByteBuffer buffer = ByteBuffer.wrap(value); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + short handle = buffer.getShort(1); + int size = buffer.getInt(4); + + byte status = buffer.get(3); + + ResultCode code = ResultCode.fromCode(status); + if(!code.inidicatesSuccess()){ + throw new RuntimeException("FileGet error: " + code + " (" + status + ")"); + } + + if(this.handle != handle){ + throw new RuntimeException("handle: " + handle + " expected: " + this.handle); + } + log("file size: " + size); + fileBuffer = ByteBuffer.allocate(size); + }else if((first & 0x0F) == 8){ + this.finished = true; + + ByteBuffer buffer = ByteBuffer.wrap(value); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + short handle = buffer.getShort(1); + if(this.handle != handle){ + throw new RuntimeException("handle: " + handle + " expected: " + this.handle); + } + + CRC32 crc = new CRC32(); + crc.update(this.fileData); + + int crcExpected = buffer.getInt(8); + + if((int) crc.getValue() != crcExpected){ + throw new RuntimeException("handle: " + handle + " expected: " + this.handle); + } + + this.handleFileRawData(this.fileData); + } + }else if(characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")){ + fileBuffer.put(value, 1, value.length - 1); + if((first & 0x80) == 0x80){ + this.fileData = fileBuffer.array(); + } + } + } + + @Override + public UUID getRequestUUID() { + return UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d"); + } + + @Override + public byte[] getStartSequence() { + return new byte[]{1}; + } + + @Override + public int getPayloadLength() { + return 11; + } + + abstract public void handleFileRawData(byte[] fileData); +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRequest.java index b9b918dde..9e33cbb70 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileGetRequest.java @@ -16,124 +16,25 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file; -import android.bluetooth.BluetoothGattCharacteristic; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.UUID; -import java.util.zip.CRC32; - -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.QHybridSupport; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.Request; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.FossilRequest; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file.ResultCode; - -public abstract class FileGetRequest extends FossilRequest { - private short handle; - private FossilWatchAdapter adapter; - - private ByteBuffer fileBuffer; - - private byte[] fileData; - - private boolean finished = false; +public abstract class FileGetRequest extends FileGetRawRequest { public FileGetRequest(short handle, FossilWatchAdapter adapter) { - this.handle = handle; - this.adapter = adapter; - - this.data = - createBuffer() - .putShort(handle) - .putInt(0) - .putInt(0xFFFFFFFF) - .array(); + super(handle, adapter); } - public FileGetRequest(FileHandle handle, FossilWatchAdapter adapter){ - this(handle.getHandle(), adapter); - } - - public FossilWatchAdapter getAdapter() { - return adapter; + public FileGetRequest(FileHandle handle, FossilWatchAdapter adapter) { + super(handle, adapter); } @Override - public boolean isFinished(){ - return finished; + public void handleFileRawData(byte[] fileData) { + byte[] file = new byte[fileData.length - 12 - 4]; // 12 = header 4 = crc end + System.arraycopy(fileData, 12, file, 0, file.length); + + this.handleFileData(file); } - @Override - public void handleResponse(BluetoothGattCharacteristic characteristic) { - byte[] value = characteristic.getValue(); - byte first = value[0]; - if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")){ - if((first & 0x0F) == 1){ - ByteBuffer buffer = ByteBuffer.wrap(value); - buffer.order(ByteOrder.LITTLE_ENDIAN); - - short handle = buffer.getShort(1); - int size = buffer.getInt(4); - - byte status = buffer.get(3); - - ResultCode code = ResultCode.fromCode(status); - if(!code.inidicatesSuccess()){ - throw new RuntimeException("FileGet error: " + code + " (" + status + ")"); - } - - if(this.handle != handle){ - throw new RuntimeException("handle: " + handle + " expected: " + this.handle); - } - log("file size: " + size); - fileBuffer = ByteBuffer.allocate(size); - }else if((first & 0x0F) == 8){ - this.finished = true; - - ByteBuffer buffer = ByteBuffer.wrap(value); - buffer.order(ByteOrder.LITTLE_ENDIAN); - - short handle = buffer.getShort(1); - if(this.handle != handle){ - throw new RuntimeException("handle: " + handle + " expected: " + this.handle); - } - - CRC32 crc = new CRC32(); - crc.update(this.fileData); - - int crcExpected = buffer.getInt(8); - - if((int) crc.getValue() != crcExpected){ - throw new RuntimeException("handle: " + handle + " expected: " + this.handle); - } - - this.handleFileData(this.fileData); - } - }else if(characteristic.getUuid().toString().equals("3dda0004-957f-7d4a-34a6-74696673696d")){ - fileBuffer.put(value, 1, value.length - 1); - if((first & 0x80) == 0x80){ - this.fileData = fileBuffer.array(); - } - } - } - - @Override - public UUID getRequestUUID() { - return UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d"); - } - - @Override - public byte[] getStartSequence() { - return new byte[]{1}; - } - - @Override - public int getPayloadLength() { - return 11; - } - - abstract public void handleFileData(byte[] fileData); + public abstract void handleFileData(byte[] fileData); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileLookupAndGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileLookupAndGetRequest.java index f42ff4f94..251c03517 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileLookupAndGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/file/FileLookupAndGetRequest.java @@ -25,9 +25,9 @@ public abstract class FileLookupAndGetRequest extends FileLookupRequest { @Override public void handleFileLookup(short fileHandle){ - getAdapter().queueWrite(new FileGetRequest(getHandle(), getAdapter()) { + getAdapter().queueWrite(new FileGetRawRequest(getHandle(), getAdapter()) { @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { FileLookupAndGetRequest.this.handleFileData(fileData); } }, true); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/notification/NotificationFilterGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/notification/NotificationFilterGetRequest.java index e50abb7be..fe20888a1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/notification/NotificationFilterGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil/notification/NotificationFilterGetRequest.java @@ -21,16 +21,16 @@ import java.nio.ByteOrder; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; import nodomain.freeyourgadget.gadgetbridge.util.CRC32C; -public class NotificationFilterGetRequest extends FileGetRequest { +public class NotificationFilterGetRequest extends FileGetRawRequest { public NotificationFilterGetRequest(FossilWatchAdapter adapter) { super(FileHandle.NOTIFICATION_FILTER, adapter); } @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { log("handleFileData"); ByteBuffer buffer = ByteBuffer.wrap(fileData); buffer.order(ByteOrder.LITTLE_ENDIAN); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/FileEncryptedLookupAndGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/FileEncryptedLookupAndGetRequest.java index a5d64d988..7644ffd63 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/FileEncryptedLookupAndGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/file/FileEncryptedLookupAndGetRequest.java @@ -16,9 +16,7 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil_hr.file; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil_hr.FossilHRWatchAdapter; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileLookupRequest; public abstract class FileEncryptedLookupAndGetRequest extends FileLookupRequest { diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java index 6383831ba..27d4c8676 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/qhybrid/requests/fossil_hr/translation/TranslationsGetRequest.java @@ -6,15 +6,15 @@ import java.util.ArrayList; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.adapter.fossil.FossilWatchAdapter; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.file.FileHandle; -import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRequest; +import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileGetRawRequest; -public abstract class TranslationsGetRequest extends FileGetRequest { +public abstract class TranslationsGetRequest extends FileGetRawRequest { public TranslationsGetRequest(FossilWatchAdapter adapter) { super(FileHandle.ASSET_TRANSLATIONS, adapter); } @Override - public void handleFileData(byte[] fileData) { + public void handleFileRawData(byte[] fileData) { ByteBuffer buffer = ByteBuffer.wrap(fileData); buffer.order(ByteOrder.LITTLE_ENDIAN);