mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
oppo: refactor OppoHeadphonesProtocol
This commit is contained in:
+119
-106
@@ -158,75 +158,17 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
LOG.warn("Unexpected firmware ret {}", payload[0]);
|
LOG.warn("Unexpected firmware ret {}", payload[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
events.addAll(parseFirmware(payload));
|
||||||
final String fwString;
|
|
||||||
if (payload[payload.length - 1] == 0) {
|
|
||||||
fwString = new String(ArrayUtils.subarray(payload, 2, payload.length - 1)).strip();
|
|
||||||
} else {
|
|
||||||
fwString = new String(ArrayUtils.subarray(payload, 2, payload.length)).strip();
|
|
||||||
}
|
|
||||||
final String[] parts = fwString.split(",");
|
|
||||||
if (parts.length % 3 != 0) {
|
|
||||||
LOG.warn("Fw parts length {} from '{}' is not divisible by 3", parts.length, fwString);
|
|
||||||
|
|
||||||
// We need to persist something, otherwise Gb misbehaves
|
|
||||||
final GBDeviceEventVersionInfo eventVersionInfo = new GBDeviceEventVersionInfo();
|
|
||||||
eventVersionInfo.fwVersion = fwString;
|
|
||||||
eventVersionInfo.hwVersion = GBApplication.getContext().getString(R.string.n_a);
|
|
||||||
events.add(eventVersionInfo);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
final String[] fwVersionParts = new String[3];
|
|
||||||
for (int i = 0; i < parts.length; i += 3) {
|
|
||||||
final String versionPart = parts[i];
|
|
||||||
final String versionType = parts[i + 1];
|
|
||||||
final String version = parts[i + 2];
|
|
||||||
if (!"2".equals(versionType)) {
|
|
||||||
continue; // not fw
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (versionPart) {
|
|
||||||
case "1":
|
|
||||||
fwVersionParts[0] = version;
|
|
||||||
break;
|
|
||||||
case "2":
|
|
||||||
fwVersionParts[1] = version;
|
|
||||||
break;
|
|
||||||
case "3":
|
|
||||||
fwVersionParts[2] = version;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.warn("Unknown firmware version part {}", versionPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<String> nonNullParts = new ArrayList<>(fwVersionParts.length);
|
|
||||||
for (int i = 0; i < fwVersionParts.length; i++) {
|
|
||||||
if (fwVersionParts[i] == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
nonNullParts.add(fwVersionParts[i]);
|
|
||||||
if (fwVersionParts[i].contains(".")) {
|
|
||||||
// Realme devices have the version already with the dots, repeated multiple times
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final String fwVersion = String.join(".", nonNullParts);
|
|
||||||
|
|
||||||
final GBDeviceEventVersionInfo eventVersionInfo = new GBDeviceEventVersionInfo();
|
|
||||||
eventVersionInfo.fwVersion = fwVersion;
|
|
||||||
eventVersionInfo.hwVersion = GBApplication.getContext().getString(R.string.n_a);
|
|
||||||
events.add(eventVersionInfo);
|
|
||||||
|
|
||||||
LOG.debug("Got fw version: {}", fwVersion);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FIND_DEVICE_ACK: {
|
case FIND_DEVICE_ACK: {
|
||||||
LOG.debug("Got find device ack, status={}", payload[0]);
|
LOG.debug("Got find device ack, status={}", payload[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PREF_ACK: {
|
||||||
|
LOG.debug("Got config ack, status={}", payload[0]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TOUCH_CONFIG_RET: {
|
case TOUCH_CONFIG_RET: {
|
||||||
if (payload[0] != 0) {
|
if (payload[0] != 0) {
|
||||||
LOG.warn("Unknown config ret {}", payload[0]);
|
LOG.warn("Unknown config ret {}", payload[0]);
|
||||||
@@ -237,39 +179,7 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences();
|
events.add(parseTouchConfig(payload));
|
||||||
|
|
||||||
for (int i = 2; i < payload.length; i += 4) {
|
|
||||||
final int sideCode = payload[i] & 0xff;
|
|
||||||
final int typeCode = BLETypeConversions.toUint16(payload, i + 1);
|
|
||||||
final int valueCode = payload[i + 3] & 0xff;
|
|
||||||
final TouchConfigSide side = TouchConfigSide.fromCode(sideCode);
|
|
||||||
final TouchConfigType type = TouchConfigType.fromCode(typeCode);
|
|
||||||
final TouchConfigValue value = TouchConfigValue.fromCode(valueCode);
|
|
||||||
|
|
||||||
if (side == null) {
|
|
||||||
LOG.warn("Unknown touch side code {}", sideCode);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (type == null) {
|
|
||||||
LOG.warn("Unknown touch type code {}", typeCode);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (value == null) {
|
|
||||||
LOG.warn("Unknown touch value code {}", valueCode);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.debug("Got touch config for {} {} = {}", side, type, value);
|
|
||||||
|
|
||||||
eventUpdatePreferences.withPreference(
|
|
||||||
OppoHeadphonesPreferences.getTouchKey(side, type),
|
|
||||||
value.name().toLowerCase(Locale.ROOT)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
events.add(eventUpdatePreferences);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOUCH_CONFIG_ACK: {
|
case TOUCH_CONFIG_ACK: {
|
||||||
@@ -312,6 +222,107 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<GBDeviceEvent> parseFirmware(final byte[] payload) {
|
||||||
|
final List<GBDeviceEvent> events = new ArrayList<>();
|
||||||
|
|
||||||
|
final String fwString;
|
||||||
|
if (payload[payload.length - 1] == 0) {
|
||||||
|
fwString = new String(ArrayUtils.subarray(payload, 2, payload.length - 1)).strip();
|
||||||
|
} else {
|
||||||
|
fwString = new String(ArrayUtils.subarray(payload, 2, payload.length)).strip();
|
||||||
|
}
|
||||||
|
final String[] parts = fwString.split(",");
|
||||||
|
if (parts.length % 3 != 0) {
|
||||||
|
LOG.warn("Fw parts length {} from '{}' is not divisible by 3", parts.length, fwString);
|
||||||
|
|
||||||
|
// We need to persist something, otherwise Gb misbehaves
|
||||||
|
final GBDeviceEventVersionInfo eventVersionInfo = new GBDeviceEventVersionInfo();
|
||||||
|
eventVersionInfo.fwVersion = fwString;
|
||||||
|
eventVersionInfo.hwVersion = GBApplication.getContext().getString(R.string.n_a);
|
||||||
|
events.add(eventVersionInfo);
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
final String[] fwVersionParts = new String[3];
|
||||||
|
for (int i = 0; i < parts.length; i += 3) {
|
||||||
|
final String versionPart = parts[i];
|
||||||
|
final String versionType = parts[i + 1];
|
||||||
|
final String version = parts[i + 2];
|
||||||
|
if (!"2".equals(versionType)) {
|
||||||
|
continue; // not fw
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (versionPart) {
|
||||||
|
case "1":
|
||||||
|
fwVersionParts[0] = version;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
fwVersionParts[1] = version;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
fwVersionParts[2] = version;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.warn("Unknown firmware version part {}", versionPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> nonNullParts = new ArrayList<>(fwVersionParts.length);
|
||||||
|
for (int i = 0; i < fwVersionParts.length; i++) {
|
||||||
|
if (fwVersionParts[i] == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nonNullParts.add(fwVersionParts[i]);
|
||||||
|
if (fwVersionParts[i].contains(".")) {
|
||||||
|
// Realme devices have the version already with the dots, repeated multiple times
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final String fwVersion = String.join(".", nonNullParts);
|
||||||
|
|
||||||
|
final GBDeviceEventVersionInfo eventVersionInfo = new GBDeviceEventVersionInfo();
|
||||||
|
eventVersionInfo.fwVersion = fwVersion;
|
||||||
|
eventVersionInfo.hwVersion = GBApplication.getContext().getString(R.string.n_a);
|
||||||
|
events.add(eventVersionInfo);
|
||||||
|
|
||||||
|
LOG.debug("Got fw version: {}", fwVersion);
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GBDeviceEvent parseTouchConfig(final byte[] payload) {
|
||||||
|
final GBDeviceEventUpdatePreferences eventUpdatePreferences = new GBDeviceEventUpdatePreferences();
|
||||||
|
|
||||||
|
for (int i = 2; i < payload.length; i += 4) {
|
||||||
|
final int sideCode = payload[i] & 0xff;
|
||||||
|
final int typeCode = BLETypeConversions.toUint16(payload, i + 1);
|
||||||
|
final int valueCode = payload[i + 3] & 0xff;
|
||||||
|
final TouchConfigSide side = TouchConfigSide.fromCode(sideCode);
|
||||||
|
final TouchConfigType type = TouchConfigType.fromCode(typeCode);
|
||||||
|
final TouchConfigValue value = TouchConfigValue.fromCode(valueCode);
|
||||||
|
|
||||||
|
if (side == null) {
|
||||||
|
LOG.warn("Unknown touch side code {}", sideCode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (type == null) {
|
||||||
|
LOG.warn("Unknown touch type code {}", typeCode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (value == null) {
|
||||||
|
LOG.warn("Unknown touch value code {}", valueCode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("Got touch config for {} {} = {}", side, type, value);
|
||||||
|
|
||||||
|
eventUpdatePreferences.withPreference(
|
||||||
|
OppoHeadphonesPreferences.getTouchKey(side, type),
|
||||||
|
value.name().toLowerCase(Locale.ROOT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return eventUpdatePreferences;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encodeFirmwareVersionReq() {
|
public byte[] encodeFirmwareVersionReq() {
|
||||||
return encodeMessage(OppoCommand.FIRMWARE_GET, new byte[0]);
|
return encodeMessage(OppoCommand.FIRMWARE_GET, new byte[0]);
|
||||||
@@ -339,14 +350,7 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
final TouchConfigValue value = TouchConfigValue.valueOf(valueCode.toUpperCase(Locale.ROOT));
|
final TouchConfigValue value = TouchConfigValue.valueOf(valueCode.toUpperCase(Locale.ROOT));
|
||||||
|
|
||||||
LOG.debug("Sending {} {} = {}", side, type, value);
|
LOG.debug("Sending {} {} = {}", side, type, value);
|
||||||
|
return encodeTouchConfigSet(side, type, value);
|
||||||
final ByteBuffer buf = ByteBuffer.allocate(5).order(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
buf.put((byte) 0x01);
|
|
||||||
buf.put((byte) side.getCode());
|
|
||||||
buf.putShort((short) type.getCode());
|
|
||||||
buf.put((byte) value.getCode());
|
|
||||||
|
|
||||||
return encodeMessage(OppoCommand.TOUCH_CONFIG_SET, buf.array());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.equals(OppoHeadphonesPreferences.LDAC)) {
|
if (config.equals(OppoHeadphonesPreferences.LDAC)) {
|
||||||
@@ -374,7 +378,16 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
return encodeMessage(OppoCommand.BATTERY_REQ, new byte[0]);
|
return encodeMessage(OppoCommand.BATTERY_REQ, new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encodeConfigurationReq() {
|
private byte[] encodeTouchConfigSet(final TouchConfigSide side, final TouchConfigType type, final TouchConfigValue value) {
|
||||||
|
final ByteBuffer buf = ByteBuffer.allocate(5).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buf.put((byte) 0x01);
|
||||||
|
buf.put((byte) side.getCode());
|
||||||
|
buf.putShort((short) type.getCode());
|
||||||
|
buf.put((byte) value.getCode());
|
||||||
|
return encodeMessage(OppoCommand.TOUCH_CONFIG_SET, buf.array());
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] encodeTouchConfigReq() {
|
||||||
return encodeMessage(OppoCommand.TOUCH_CONFIG_REQ, new byte[]{0x02, 0x03, 0x01});
|
return encodeMessage(OppoCommand.TOUCH_CONFIG_REQ, new byte[]{0x02, 0x03, 0x01});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,7 +412,7 @@ public class OppoHeadphonesProtocol extends GBDeviceProtocol {
|
|||||||
return encodePrefSet(PrefType.MULTIPOINT, payload);
|
return encodePrefSet(PrefType.MULTIPOINT, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] encodePrefSet(final PrefType type, final byte[] value) {
|
private byte[] encodePrefSet(final PrefType type, final byte[] value) {
|
||||||
final byte[] payload = new byte[1 + value.length];
|
final byte[] payload = new byte[1 + value.length];
|
||||||
payload[0] = (byte) type.getCode();
|
payload[0] = (byte) type.getCode();
|
||||||
System.arraycopy(value, 0, payload, 1, value.length);
|
System.arraycopy(value, 0, payload, 1, value.length);
|
||||||
|
|||||||
+1
-1
@@ -70,7 +70,7 @@ public class OppoHeadphonesSupport extends AbstractHeadphoneSerialDeviceSupportV
|
|||||||
@Override
|
@Override
|
||||||
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
|
||||||
builder.write(mDeviceProtocol.encodeFirmwareVersionReq());
|
builder.write(mDeviceProtocol.encodeFirmwareVersionReq());
|
||||||
builder.write(mDeviceProtocol.encodeConfigurationReq());
|
builder.write(mDeviceProtocol.encodeTouchConfigReq());
|
||||||
builder.write(mDeviceProtocol.encodeBatteryReq());
|
builder.write(mDeviceProtocol.encodeBatteryReq());
|
||||||
builder.setDeviceState(GBDevice.State.INITIALIZED);
|
builder.setDeviceState(GBDevice.State.INITIALIZED);
|
||||||
scheduleBatteryRequestRetry();
|
scheduleBatteryRequestRetry();
|
||||||
|
|||||||
Reference in New Issue
Block a user