Sony: Read LDAC and NC/AMBIENT button value on connection

This commit is contained in:
José Rebelo
2026-04-19 16:24:36 +01:00
parent 0e85d47cc8
commit 9badec8e3a
5 changed files with 93 additions and 20 deletions
@@ -45,6 +45,16 @@ public class ButtonFunctionNcAmbient {
return code;
}
public static ButtonFunctionNcAmbient.Mode fromCode(final byte b) {
for (ButtonFunctionNcAmbient.Mode value : ButtonFunctionNcAmbient.Mode.values()) {
if (value.getCode() == b) {
return value;
}
}
return null;
}
public static Mode fromPrefValue(final String prefValue) {
for (final Mode mode : values()) {
if (mode.prefValue.equals(prefValue)) {
@@ -86,7 +86,7 @@ public class Message {
public String toString() {
if (payload.length > 0) {
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d, PayloadType=%d, Payload=%s}", type, sequenceNumber, payload[0], GB.hexdump(payload));
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d, PayloadType=%s, Payload=%s}", type, sequenceNumber, String.format("0x%02x", payload[0]), GB.hexdump(payload));
} else {
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d}", type, sequenceNumber);
}
@@ -88,8 +88,12 @@ public abstract class AbstractSonyProtocolImpl {
public abstract Request getAudioUpsampling();
public abstract Request getAudioLDAC();
public abstract Request setAudioLDAC(final AudioLDAC config);
public abstract Request getButtonFunctionNcAmbient();
public abstract Request setButtonFunctionNcAmbient(final ButtonFunctionNcAmbient config);
public abstract Request setAudioUpsampling(final AudioUpsampling config);
@@ -261,6 +261,17 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
);
}
@Override
public Request getAudioLDAC() {
return new Request(
PayloadTypeV1.AUDIO_UPSAMPLING_GET.getMessageType(),
new byte[]{
PayloadTypeV1.AUDIO_UPSAMPLING_GET.getCode(),
(byte) 0x01
}
);
}
@Override
public Request setAudioLDAC(final AudioLDAC config) {
return new Request(
@@ -274,6 +285,17 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
);
}
@Override
public Request getButtonFunctionNcAmbient() {
return new Request(
PayloadTypeV1.TOUCH_SENSOR_GET.getMessageType(),
new byte[]{
PayloadTypeV1.TOUCH_SENSOR_GET.getCode(),
(byte) 0xd1
}
);
}
@Override
public Request setButtonFunctionNcAmbient(final ButtonFunctionNcAmbient config) {
return new Request(
@@ -675,7 +697,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
capabilityRequests.add(getFirmwareVersion());
capabilityRequests.add(getAudioCodec());
final Map<SonyHeadphonesCapabilities, Request> capabilityRequestMap = new LinkedHashMap<SonyHeadphonesCapabilities, Request>() {{
final Map<SonyHeadphonesCapabilities, Request> capabilityRequestMap = new LinkedHashMap<>() {{
put(SonyHeadphonesCapabilities.BatterySingle, getBattery(BatteryType.SINGLE));
put(SonyHeadphonesCapabilities.BatteryDual, getBattery(BatteryType.DUAL));
put(SonyHeadphonesCapabilities.BatteryDual2, getBattery(BatteryType.DUAL2));
@@ -684,6 +706,8 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
put(SonyHeadphonesCapabilities.AmbientSoundControl2, getAmbientSoundControl());
put(SonyHeadphonesCapabilities.AncOptimizer, getNoiseCancellingOptimizerState());
put(SonyHeadphonesCapabilities.AudioUpsampling, getAudioUpsampling());
put(SonyHeadphonesCapabilities.AudioLDAC, getAudioLDAC());
put(SonyHeadphonesCapabilities.ButtonFunctionNcAmbient, getButtonFunctionNcAmbient());
put(SonyHeadphonesCapabilities.ButtonModesLeftRight, getButtonModes());
put(SonyHeadphonesCapabilities.VoiceNotifications, getVoiceNotifications());
put(SonyHeadphonesCapabilities.AutomaticPowerOffWhenTakenOff, getAutomaticPowerOff());
@@ -856,14 +880,27 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
final Boolean enabled = booleanFromByte(payload[3]);
if (enabled == null) {
LOG.warn("Unknown audio upsampling code {}", String.format("%02x", payload[3]));
LOG.warn("Unknown audio upsampling value {}", String.format("%02x", payload[3]));
return Collections.emptyList();
}
LOG.debug("Audio Upsampling: {}", enabled);
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences();
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
.withPreferences(new AudioUpsampling(enabled).toPreferences());
switch (payload[1]) {
case 0x01:
// LDAC
LOG.debug("Audio Upsampling LDAC: {}", !enabled);
event.withPreferences(new AudioLDAC(!enabled).toPreferences());
break;
case 0x02:
// DSEE / Audio upsampling
LOG.debug("Audio Upsampling DSEE: {}", enabled);
event.withPreferences(new AudioUpsampling(enabled).toPreferences());
break;
default:
LOG.warn("Unknown audio upsampling code {}", String.format("%02x", payload[1]));
return Collections.emptyList();
}
return Collections.singletonList(event);
}
@@ -1215,8 +1252,16 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
boolean enabled;
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences();
switch (payload[1]) {
case (byte) 0xd1:
final ButtonFunctionNcAmbient.Mode mode = ButtonFunctionNcAmbient.Mode.fromCode(payload[3]);
event.withPreferences(new ButtonFunctionNcAmbient(mode).toPreferences());
LOG.debug("Nc Ambient button mode: {}", mode);
break;
case (byte) 0xd2:
boolean enabled;
switch (payload[3]) {
case 0x00:
enabled = false;
@@ -1225,14 +1270,16 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
enabled = true;
break;
default:
LOG.warn("Unknown touch sensor code {}", String.format("%02x", payload[3]));
LOG.warn("Unknown touch sensor value {}", String.format("%02x", payload[3]));
return Collections.emptyList();
}
LOG.debug("Touch Sensor: {}", enabled);
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
.withPreferences(new TouchSensor(enabled).toPreferences());
event.withPreferences(new TouchSensor(enabled).toPreferences());
break;
default:
LOG.warn("Unknown touch sensor code {}", String.format("%02x", payload[1]));
return Collections.emptyList();
}
return Collections.singletonList(event);
}
@@ -225,15 +225,27 @@ public class SonyProtocolImplV2 extends SonyProtocolImplV1 {
);
}
@Override
public Request getAudioLDAC() {
LOG.warn("Audio LDAC get not implemented for V2");
return null;
}
@Override
public Request setAudioLDAC(final AudioLDAC config) {
LOG.warn("Audio LDAC not implemented for V2");
LOG.warn("Audio LDAC set not implemented for V2");
return null;
}
@Override
public Request getButtonFunctionNcAmbient() {
LOG.warn("Button function NC ambient get not implemented for V2");
return null;
}
@Override
public Request setButtonFunctionNcAmbient(final ButtonFunctionNcAmbient config) {
LOG.warn("Button function NC ambient not implemented for V2");
LOG.warn("Button function NC ambient set not implemented for V2");
return null;
}