adjusted some MTU specific file handling

This commit is contained in:
Daniel Dakhno 2019-11-16 02:14:45 +01:00
parent 5cab9fa9da
commit 56d5b95181
3 changed files with 70 additions and 56 deletions

View File

@ -6,20 +6,15 @@ import android.os.Build;
import android.util.Log; import android.util.Log;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.RequiresApi;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.Logging;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.NotificationConfiguration;
import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfigHelper; import nodomain.freeyourgadget.gadgetbridge.devices.qhybrid.PackageConfigHelper;
import nodomain.freeyourgadget.gadgetbridge.entities.NotificationFilter;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.GenericItem; import nodomain.freeyourgadget.gadgetbridge.model.GenericItem;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
@ -31,11 +26,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.SetDeviceStateRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationGetRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationGetRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.configuration.ConfigurationPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.connection.SetConnectionParametersRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileCloseRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileDeleteRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FilePutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.file.FileVerifyRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.NotificationFilterPutRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.NotificationFilterPutRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil.notification.PlayNotificationRequest;
import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest; import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.misfit.AnimationRequest;
@ -49,6 +40,10 @@ public class FossilWatchAdapter extends WatchAdapter {
private FossilRequest fossilRequest; private FossilRequest fossilRequest;
private int MTU = 23;
private String ITEM_MTU = "MTU";
public FossilWatchAdapter(QHybridSupport deviceSupport) { public FossilWatchAdapter(QHybridSupport deviceSupport) {
super(deviceSupport); super(deviceSupport);
} }
@ -57,16 +52,22 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void initialize() { public void initialize() {
playPairingAnimation(); playPairingAnimation();
// queueWrite(new FileDeleteRequest((short) 0x0200)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
queueWrite(new RequestMtuRequest(512)); queueWrite(new RequestMtuRequest(512));
}
queueWrite(new ConfigurationGetRequest(this)); queueWrite(new ConfigurationGetRequest(this));
// queueWrite(new SetConnectionParametersRequest());
syncNotificationSettings(); syncNotificationSettings();
queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED)); queueWrite(new SetDeviceStateRequest(GBDevice.State.INITIALIZED));
} }
public int getMTU(){
if(this.MTU < 0) throw new RuntimeException("MTU not configured");
return this.MTU;
}
@Override @Override
public void playPairingAnimation() { public void playPairingAnimation() {
queueWrite(new AnimationRequest()); queueWrite(new AnimationRequest());
@ -315,6 +316,11 @@ public class FossilWatchAdapter extends WatchAdapter {
@Override @Override
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
super.onMtuChanged(gatt, mtu, status); super.onMtuChanged(gatt, mtu, status);
this.MTU = mtu;
getDeviceSupport().getDevice().addDeviceInfo(new GenericItem(ITEM_MTU, String.valueOf(mtu)));
getDeviceSupport().getDevice().sendDeviceUpdateIntent(getContext());
((RequestMtuRequest)fossilRequest).setFinished(true); ((RequestMtuRequest)fossilRequest).setFinished(true);
try { try {
queueWrite(requestQueue.remove(0)); queueWrite(requestQueue.remove(0));
@ -325,7 +331,6 @@ public class FossilWatchAdapter extends WatchAdapter {
//TODO split to multiple methods instead of switch //TODO split to multiple methods instead of switch
public void queueWrite(Request request, boolean priorise) { public void queueWrite(Request request, boolean priorise) {
if(request instanceof RequestMtuRequest){ if(request instanceof RequestMtuRequest){
//TODO mtu on older devices
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
new TransactionBuilder("requestMtu") new TransactionBuilder("requestMtu")
.requestMtu(512) .requestMtu(512)

View File

@ -1,9 +1,14 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil; package nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fossil;
import android.os.Build;
import androidx.annotation.RequiresApi;
public class RequestMtuRequest extends FossilRequest { public class RequestMtuRequest extends FossilRequest {
private int mtu; private int mtu;
private boolean finished = false; private boolean finished = false;
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public RequestMtuRequest(int mtu) { public RequestMtuRequest(int mtu) {
this.mtu = mtu; this.mtu = mtu;
} }

View File

@ -17,7 +17,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.qhybrid.requests.fos
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class FilePutRequest extends FossilRequest { public class FilePutRequest extends FossilRequest {
public enum UploadState{INITIALIZED, UPLOADING, CLOSING, UPLOADED} public enum UploadState {INITIALIZED, UPLOADING, CLOSING, UPLOADED}
public UploadState state; public UploadState state;
@ -29,6 +29,8 @@ public class FilePutRequest extends FossilRequest {
private FossilWatchAdapter adapter; private FossilWatchAdapter adapter;
byte[] file;
public FilePutRequest(short handle, byte[] file, FossilWatchAdapter adapter) { public FilePutRequest(short handle, byte[] file, FossilWatchAdapter adapter) {
this.handle = handle; this.handle = handle;
this.adapter = adapter; this.adapter = adapter;
@ -42,7 +44,7 @@ public class FilePutRequest extends FossilRequest {
this.data = buffer.array(); this.data = buffer.array();
prepareFilePackets(file); this.file = file;
state = UploadState.INITIALIZED; state = UploadState.INITIALIZED;
} }
@ -54,7 +56,7 @@ public class FilePutRequest extends FossilRequest {
@Override @Override
public void handleResponse(BluetoothGattCharacteristic characteristic) { public void handleResponse(BluetoothGattCharacteristic characteristic) {
byte[] value = characteristic.getValue(); byte[] value = characteristic.getValue();
if(characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")) { if (characteristic.getUuid().toString().equals("3dda0003-957f-7d4a-34a6-74696673696d")) {
int responseType = value[0] & 0x0F; int responseType = value[0] & 0x0F;
log("response: " + responseType); log("response: " + responseType);
switch (responseType) { switch (responseType) {
@ -63,15 +65,17 @@ public class FilePutRequest extends FossilRequest {
throw new RuntimeException("wrong answer header"); throw new RuntimeException("wrong answer header");
} }
state = UploadState.UPLOADING; state = UploadState.UPLOADING;
byte[] initialPacket = packets.get(0);
BtLEQueue queue = adapter.getDeviceSupport().getQueue();
new TransactionBuilder("file upload") TransactionBuilder transactionBuilder = new TransactionBuilder("file upload");
.write( BluetoothGattCharacteristic uploadCharacteristic = adapter.getDeviceSupport().getCharacteristic(UUID.fromString("3dda0004-957f-7d4a-34a6-74696673696d"));
adapter.getDeviceSupport().getCharacteristic(UUID.fromString("3dda0004-957f-7d4a-34a6-74696673696d")),
initialPacket this.prepareFilePackets(this.file);
)
.queue(queue); for (byte[] packet : packets) {
transactionBuilder.write(uploadCharacteristic, packet);
}
transactionBuilder.queue(adapter.getDeviceSupport().getQueue());
break; break;
} }
case 8: { case 8: {
@ -101,34 +105,21 @@ public class FilePutRequest extends FossilRequest {
// break; // break;
} }
packetIndex++;
if (packetIndex < packets.size()) { ByteBuffer buffer2 = ByteBuffer.allocate(3);
byte[] initialPacket = packets.get(packetIndex); buffer2.order(ByteOrder.LITTLE_ENDIAN);
buffer2.put((byte) 4);
buffer2.putShort(this.handle);
new TransactionBuilder("file upload") new TransactionBuilder("file close")
.write( .write(
adapter.getDeviceSupport().getCharacteristic(UUID.fromString("3dda0004-957f-7d4a-34a6-74696673696d")), adapter.getDeviceSupport().getCharacteristic(UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d")),
initialPacket buffer2.array()
) )
.queue(adapter.getDeviceSupport().getQueue()); .queue(adapter.getDeviceSupport().getQueue());
break;
} else {
ByteBuffer buffer2 = ByteBuffer.allocate(3);
buffer2.order(ByteOrder.LITTLE_ENDIAN);
buffer2.put((byte) 4);
buffer2.putShort(this.handle);
new TransactionBuilder("file close") this.state = UploadState.CLOSING;
.write( break;
adapter.getDeviceSupport().getCharacteristic(UUID.fromString("3dda0003-957f-7d4a-34a6-74696673696d")),
buffer2.array()
)
.queue(adapter.getDeviceSupport().getQueue());
this.state = UploadState.CLOSING;
break;
}
} }
case 4: { case 4: {
if (value.length == 9) return; if (value.length == 9) return;
@ -184,18 +175,19 @@ public class FilePutRequest extends FossilRequest {
} }
@Override @Override
public boolean isFinished(){ public boolean isFinished() {
return this.state == UploadState.UPLOADED; return this.state == UploadState.UPLOADED;
} }
private void prepareFilePackets(byte[] file) { private void prepareFilePackets(byte[] file) {
ByteBuffer buffer = ByteBuffer.allocate(file.length + 13 + 4); int maxPacketSize = adapter.getMTU() - 4;
ByteBuffer buffer = ByteBuffer.allocate(file.length + 12 + 4);
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte)0);
buffer.putShort(handle); buffer.putShort(handle);
buffer.put((byte)2); buffer.put((byte) 2);
buffer.put((byte)0); buffer.put((byte) 0);
buffer.putInt(0); buffer.putInt(0);
buffer.putInt(file.length); buffer.putInt(file.length);
@ -206,10 +198,22 @@ public class FilePutRequest extends FossilRequest {
crc.update(file); crc.update(file);
buffer.putInt((int) crc.getValue()); buffer.putInt((int) crc.getValue());
packets.add(buffer.array()); byte[] data = buffer.array();
int packetCount = (int) Math.ceil(data.length / (float) maxPacketSize);
for (int i = 0; i < packetCount; i++) {
int currentPacketLength = Math.min(maxPacketSize, data.length - i * maxPacketSize);
byte[] packet = new byte[currentPacketLength + 1];
packet[0] = (byte) i;
System.arraycopy(data, i * maxPacketSize, packet, 1, currentPacketLength);
packets.add(packet);
}
} }
public void onFilePut(boolean success){} public void onFilePut(boolean success) {
}
@Override @Override
public byte[] getStartSequence() { public byte[] getStartSequence() {