mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-09-01 03:55:47 +02:00
Garmin: further work for auth negotiation
Add status message parsing and change the reply logic for watch-initiated Auth (in attempt to fix #3986): before this changeset the phone would reply with a generic ACK and then send a request to the watch for setting the auth (with all zeroes); after this changeset the phone replies with a specific auth ack/status message but it ignores what the watch requested and acknowledges back all zeroes. Blindly implemented based on the legacy vivomoveHR code, not tested against real devices.
This commit is contained in:
parent
d1b4e013d3
commit
7fa5cd1be5
@ -4,6 +4,8 @@ import org.apache.commons.lang3.EnumUtils;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status.AuthNegotiationStatusMessage;
|
||||
|
||||
public class AuthNegotiationMessage extends GFDIMessage {
|
||||
|
||||
private final int unknown;
|
||||
@ -16,7 +18,7 @@ public class AuthNegotiationMessage extends GFDIMessage {
|
||||
|
||||
LOG.info("Message {}, unkByte: {}, flags: {}", garminMessage, unknown, requestedAuthFlags);
|
||||
|
||||
this.statusMessage = getStatusMessage();
|
||||
this.statusMessage = new AuthNegotiationStatusMessage(garminMessage, Status.ACK, AuthNegotiationStatusMessage.AuthNegotiationStatus.GUESS_OK, 0, EnumSet.noneOf(AuthFlags.class));
|
||||
}
|
||||
|
||||
public static AuthNegotiationMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
|
||||
@ -38,10 +40,10 @@ public class AuthNegotiationMessage extends GFDIMessage {
|
||||
writer.writeByte(0);
|
||||
writer.writeInt((int) EnumUtils.generateBitVector(AuthFlags.class, EnumSet.noneOf(AuthFlags.class)));
|
||||
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private enum AuthFlags {
|
||||
public enum AuthFlags {
|
||||
UNK_00000001, //saw in logs
|
||||
UNK_00000010,
|
||||
UNK_00000100,
|
||||
|
@ -0,0 +1,83 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.status;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.EnumUtils;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.AuthNegotiationMessage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.MessageWriter;
|
||||
|
||||
public class AuthNegotiationStatusMessage extends GFDIStatusMessage {
|
||||
|
||||
private final Status status;
|
||||
private final AuthNegotiationStatus authNegotiationStatus;
|
||||
private final int unknown;
|
||||
private final EnumSet<AuthNegotiationMessage.AuthFlags> authFlags;
|
||||
private final boolean sendOutgoing;
|
||||
|
||||
public AuthNegotiationStatusMessage(GarminMessage garminMessage, Status status, AuthNegotiationStatus authNegotiationStatus, int unknown, EnumSet<AuthNegotiationMessage.AuthFlags> authFlags) {
|
||||
this(garminMessage, status, authNegotiationStatus, unknown, authFlags, true);
|
||||
}
|
||||
|
||||
public AuthNegotiationStatusMessage(GarminMessage garminMessage, Status status, AuthNegotiationStatus authNegotiationStatus, int unknown, EnumSet<AuthNegotiationMessage.AuthFlags> authFlags, boolean sendOutgoing) {
|
||||
this.garminMessage = garminMessage;
|
||||
this.status = status;
|
||||
this.authNegotiationStatus = authNegotiationStatus;
|
||||
this.unknown = unknown;
|
||||
this.authFlags = authFlags;
|
||||
this.sendOutgoing = sendOutgoing;
|
||||
}
|
||||
|
||||
public static AuthNegotiationStatusMessage parseIncoming(MessageReader reader, GarminMessage garminMessage) {
|
||||
final Status status = Status.fromCode(reader.readByte());
|
||||
final int authNegotiationStatusCode = reader.readByte();
|
||||
final AuthNegotiationStatus authNegotiationStatus = AuthNegotiationStatus.fromCode(authNegotiationStatusCode);
|
||||
if (null == authNegotiationStatus) {
|
||||
LOG.warn("Unknown auth negotiation status code {}", authNegotiationStatusCode);
|
||||
return null;
|
||||
}
|
||||
final int unk = reader.readByte();
|
||||
final EnumSet<AuthNegotiationMessage.AuthFlags> authFlags = AuthNegotiationMessage.AuthFlags.fromBitMask(reader.readInt());
|
||||
|
||||
switch (authNegotiationStatus) {
|
||||
case GUESS_OK:
|
||||
LOG.info("Received {}/{} for message {} unkByte: {}, flags: {}", status, authNegotiationStatus, garminMessage, unk, authFlags);
|
||||
break;
|
||||
default:
|
||||
LOG.warn("Received {}/{} for message {} unkByte: {}, flags: {}", status, authNegotiationStatus, garminMessage, unk, authFlags);
|
||||
}
|
||||
return new AuthNegotiationStatusMessage(garminMessage, status, authNegotiationStatus, unk, authFlags, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean generateOutgoing() {
|
||||
final MessageWriter writer = new MessageWriter(response);
|
||||
writer.writeShort(0); // packet size will be filled below
|
||||
writer.writeShort(GarminMessage.RESPONSE.getId());
|
||||
writer.writeShort(garminMessage.getId());
|
||||
writer.writeByte(status.ordinal());
|
||||
writer.writeByte(authNegotiationStatus.ordinal());
|
||||
writer.writeByte(unknown);
|
||||
writer.writeInt((int) EnumUtils.generateBitVector(AuthNegotiationMessage.AuthFlags.class, authFlags));
|
||||
|
||||
return sendOutgoing;
|
||||
}
|
||||
|
||||
public enum AuthNegotiationStatus {
|
||||
GUESS_OK,
|
||||
GUESS_KO,
|
||||
;
|
||||
|
||||
@Nullable
|
||||
public static AuthNegotiationStatus fromCode(final int code) {
|
||||
for (final AuthNegotiationStatus authNegotiationStatus : AuthNegotiationStatus.values()) {
|
||||
if (authNegotiationStatus.ordinal() == code) {
|
||||
return authNegotiationStatus;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,8 @@ public abstract class GFDIStatusMessage extends GFDIMessage {
|
||||
return FitDefinitionStatusMessage.parseIncoming(reader, originalGarminMessage);
|
||||
} else if (GarminMessage.FIT_DATA.equals(originalGarminMessage)) {
|
||||
return FitDataStatusMessage.parseIncoming(reader, originalGarminMessage);
|
||||
} else if (GarminMessage.AUTH_NEGOTIATION.equals(originalGarminMessage)) {
|
||||
return AuthNegotiationStatusMessage.parseIncoming(reader, originalGarminMessage);
|
||||
} else {
|
||||
final Status status = Status.fromCode(reader.readByte());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user