1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-07-22 06:41:06 +02:00

Sony Headphones: Refactor V1 protocol to simplify V2 implementation

This commit is contained in:
José Rebelo 2022-10-19 20:50:39 +01:00
parent 1dca054853
commit d4ba532b11
10 changed files with 185 additions and 156 deletions

View File

@ -24,7 +24,6 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCapabilities;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.headphones.SonyHeadphonesCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;

View File

@ -36,7 +36,7 @@ public class AmbientSoundControl {
private final boolean focusOnVoice;
private final int ambientSound;
public AmbientSoundControl(Mode mode, boolean focusOnVoice, int ambientSound) {
public AmbientSoundControl(final Mode mode, final boolean focusOnVoice, final int ambientSound) {
if (ambientSound < 0 || ambientSound > 20) {
throw new IllegalArgumentException(String.format("Level must be between 0 and 20 (was %d)", ambientSound));
}

View File

@ -48,6 +48,16 @@ public enum AutomaticPowerOff {
}};
}
public static AutomaticPowerOff fromCode(final byte b1, final byte b2) {
for (AutomaticPowerOff value : AutomaticPowerOff.values()) {
if (value.getCode()[0] == b1 && value.getCode()[1] == b2) {
return value;
}
}
return null;
}
public static AutomaticPowerOff fromPreferences(final SharedPreferences prefs) {
return AutomaticPowerOff.valueOf(prefs.getString(DeviceSettingsPreferenceConst.PREF_SONY_AUTOMATIC_POWER_OFF, "off").toUpperCase());
}

View File

@ -40,6 +40,16 @@ public class ButtonModes {
public byte getCode() {
return this.code;
}
public static Mode fromCode(final byte code) {
for (ButtonModes.Mode value : ButtonModes.Mode.values()) {
if (value.getCode() == code) {
return value;
}
}
return null;
}
}
final Mode left;

View File

@ -54,6 +54,16 @@ public enum EqualizerPreset {
}};
}
public static EqualizerPreset fromCode(final byte code) {
for (EqualizerPreset value : EqualizerPreset.values()) {
if (value.getCode() == code) {
return value;
}
}
return null;
}
public static EqualizerPreset fromPreferences(final SharedPreferences prefs) {
return EqualizerPreset.valueOf(prefs.getString(DeviceSettingsPreferenceConst.PREF_SONY_EQUALIZER_MODE, "off").toUpperCase());
}

View File

@ -208,6 +208,11 @@ public class SonyHeadphonesProtocol extends GBDeviceProtocol {
return super.encodeSendConfiguration(config);
}
if (configRequest == null) {
LOG.warn("Failed to encode config request for {}", config);
return super.encodeSendConfiguration(config);
}
pendingAcks++;
return configRequest.encode(sequenceNumber);

View File

@ -25,7 +25,6 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.impl.v1.PayloadType;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class Message {
@ -38,7 +37,7 @@ public class Message {
* - Message Type ({@link MessageType})
* - Sequence Number - needs to be updated with the one sent in the ACK responses
* - Payload Length - 4-byte big endian int with number of bytes that will follow
* - N bytes of payload data (first being the {@link PayloadType})
* - N bytes of payload data (first being the PayloadType)
* - Checksum (1-byte sum, excluding header)
* - MESSAGE_TRAILER
* <p>
@ -87,8 +86,7 @@ public class Message {
public String toString() {
if (payload.length > 0) {
final PayloadType payloadType = PayloadType.fromCode(type, payload[0]);
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d, PayloadType=%s, Payload=%s}", type, sequenceNumber, payloadType, GB.hexdump(payload));
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d, PayloadType=%d, Payload=%s}", type, sequenceNumber, payload[0], GB.hexdump(payload));
} else {
return String.format(Locale.getDefault(), "Message{Cmd=%s, Seq=%d}", type, sequenceNumber);
}

View File

@ -18,7 +18,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.pro
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.MessageType;
public enum PayloadType {
public enum PayloadTypeV1 {
INIT_REQUEST(MessageType.COMMAND_1, 0x00),
INIT_REPLY(MessageType.COMMAND_1, 0x01),
@ -93,7 +93,7 @@ public enum PayloadType {
private final MessageType messageType;
private final byte code;
PayloadType(final MessageType messageType, final int code) {
PayloadTypeV1(final MessageType messageType, final int code) {
this.messageType = messageType;
this.code = (byte) code;
}
@ -106,13 +106,13 @@ public enum PayloadType {
return this.code;
}
public static PayloadType fromCode(final MessageType messageType, final byte code) {
for (final PayloadType payloadType : values()) {
public static PayloadTypeV1 fromCode(final MessageType messageType, final byte code) {
for (final PayloadTypeV1 payloadType : values()) {
if (messageType.equals(payloadType.messageType) && payloadType.code == code) {
return payloadType;
}
}
return PayloadType.UNKNOWN;
return PayloadTypeV1.UNKNOWN;
}
}

View File

@ -61,7 +61,6 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.prot
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.impl.v1.params.BatteryType;
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.impl.v1.params.NoiseCancellingOptimizerStatus;
import nodomain.freeyourgadget.gadgetbridge.service.devices.sony.headphones.protocol.impl.v1.params.VirtualSoundParam;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@ -74,9 +73,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getAmbientSoundControl() {
return new Request(
PayloadType.AMBIENT_SOUND_CONTROL_GET.getMessageType(),
PayloadTypeV1.AMBIENT_SOUND_CONTROL_GET.getMessageType(),
new byte[]{
PayloadType.AMBIENT_SOUND_CONTROL_GET.getCode(),
PayloadTypeV1.AMBIENT_SOUND_CONTROL_GET.getCode(),
(byte) 0x02
}
);
@ -86,7 +85,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
public Request setAmbientSoundControl(final AmbientSoundControl ambientSoundControl) {
final ByteBuffer buf = ByteBuffer.allocate(8);
buf.put(PayloadType.AMBIENT_SOUND_CONTROL_SET.getCode());
buf.put(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getCode());
buf.put((byte) 0x02);
if (AmbientSoundControl.Mode.OFF.equals(ambientSoundControl.getMode())) {
@ -135,15 +134,15 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
break;
}
return new Request(PayloadType.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
return new Request(PayloadTypeV1.AMBIENT_SOUND_CONTROL_SET.getMessageType(), buf.array());
}
@Override
public Request getNoiseCancellingOptimizerState() {
return new Request(
PayloadType.NOISE_CANCELLING_OPTIMIZER_STATE_GET.getMessageType(),
PayloadTypeV1.NOISE_CANCELLING_OPTIMIZER_STATE_GET.getMessageType(),
new byte[]{
PayloadType.NOISE_CANCELLING_OPTIMIZER_STATE_GET.getCode(),
PayloadTypeV1.NOISE_CANCELLING_OPTIMIZER_STATE_GET.getCode(),
(byte) 0x01
}
);
@ -152,21 +151,21 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getAudioCodec() {
return new Request(
PayloadType.AUDIO_CODEC_REQUEST.getMessageType(),
PayloadTypeV1.AUDIO_CODEC_REQUEST.getMessageType(),
new byte[]{
PayloadType.AUDIO_CODEC_REQUEST.getCode(),
PayloadTypeV1.AUDIO_CODEC_REQUEST.getCode(),
(byte) 0x00
}
);
}
@Override
public Request getBattery(BatteryType batteryType) {
public Request getBattery(final BatteryType batteryType) {
return new Request(
PayloadType.BATTERY_LEVEL_REQUEST.getMessageType(),
PayloadTypeV1.BATTERY_LEVEL_REQUEST.getMessageType(),
new byte[]{
PayloadType.BATTERY_LEVEL_REQUEST.getCode(),
batteryType.getCode()
PayloadTypeV1.BATTERY_LEVEL_REQUEST.getCode(),
encodeBatteryType(batteryType)
}
);
}
@ -174,9 +173,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getFirmwareVersion() {
return new Request(
PayloadType.FW_VERSION_REQUEST.getMessageType(),
PayloadTypeV1.FW_VERSION_REQUEST.getMessageType(),
new byte[]{
PayloadType.FW_VERSION_REQUEST.getCode(),
PayloadTypeV1.FW_VERSION_REQUEST.getCode(),
(byte) 0x02
}
);
@ -185,20 +184,20 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getAudioUpsampling() {
return new Request(
PayloadType.AUDIO_UPSAMPLING_GET.getMessageType(),
PayloadTypeV1.AUDIO_UPSAMPLING_GET.getMessageType(),
new byte[]{
PayloadType.AUDIO_UPSAMPLING_GET.getCode(),
PayloadTypeV1.AUDIO_UPSAMPLING_GET.getCode(),
(byte) 0x02
}
);
}
@Override
public Request setAudioUpsampling(AudioUpsampling config) {
public Request setAudioUpsampling(final AudioUpsampling config) {
return new Request(
PayloadType.AUDIO_UPSAMPLING_SET.getMessageType(),
PayloadTypeV1.AUDIO_UPSAMPLING_SET.getMessageType(),
new byte[]{
PayloadType.AUDIO_UPSAMPLING_SET.getCode(),
PayloadTypeV1.AUDIO_UPSAMPLING_SET.getCode(),
(byte) 0x02,
(byte) 0x00,
(byte) (config.isEnabled() ? 0x01 : 0x00)
@ -209,9 +208,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getAutomaticPowerOff() {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
(byte) 0x04
}
);
@ -220,9 +219,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setAutomaticPowerOff(final AutomaticPowerOff config) {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
(byte) 0x04,
(byte) 0x01,
config.getCode()[0],
@ -233,9 +232,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
public Request getButtonModes() {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
(byte) 0x06
}
);
@ -243,9 +242,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
public Request setButtonModes(final ButtonModes config) {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
(byte) 0x06,
(byte) 0x02,
config.getModeLeft().getCode(),
@ -257,9 +256,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getPauseWhenTakenOff() {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_GET.getCode(),
(byte) 0x03
}
);
@ -268,9 +267,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setPauseWhenTakenOff(final PauseWhenTakenOff config) {
return new Request(
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getMessageType(),
new byte[]{
PayloadType.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
PayloadTypeV1.AUTOMATIC_POWER_OFF_BUTTON_MODE_SET.getCode(),
(byte) 0x03,
(byte) 0x00,
(byte) (config.isEnabled() ? 0x01 : 0x00)
@ -281,9 +280,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getEqualizer() {
return new Request(
PayloadType.EQUALIZER_GET.getMessageType(),
PayloadTypeV1.EQUALIZER_GET.getMessageType(),
new byte[]{
PayloadType.EQUALIZER_GET.getCode(),
PayloadTypeV1.EQUALIZER_GET.getCode(),
(byte) 0x01
}
);
@ -292,9 +291,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setEqualizerPreset(final EqualizerPreset config) {
return new Request(
PayloadType.EQUALIZER_SET.getMessageType(),
PayloadTypeV1.EQUALIZER_SET.getMessageType(),
new byte[]{
PayloadType.EQUALIZER_SET.getCode(),
PayloadTypeV1.EQUALIZER_SET.getCode(),
(byte) 0x01,
config.getCode(),
(byte) 0x00
@ -306,7 +305,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
public Request setEqualizerCustomBands(final EqualizerCustomBands config) {
final ByteBuffer buf = ByteBuffer.allocate(10);
buf.put(PayloadType.EQUALIZER_SET.getCode());
buf.put(PayloadTypeV1.EQUALIZER_SET.getCode());
buf.put((byte) 0x01);
buf.put((byte) 0xff);
buf.put((byte) 0x06);
@ -317,7 +316,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
}
return new Request(
PayloadType.EQUALIZER_SET.getMessageType(),
PayloadTypeV1.EQUALIZER_SET.getMessageType(),
buf.array()
);
}
@ -325,9 +324,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getSoundPosition() {
return new Request(
PayloadType.SOUND_POSITION_OR_MODE_GET.getMessageType(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_GET.getMessageType(),
new byte[]{
PayloadType.SOUND_POSITION_OR_MODE_GET.getCode(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_GET.getCode(),
(byte) 0x02
}
);
@ -336,9 +335,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setSoundPosition(final SoundPosition config) {
return new Request(
PayloadType.SOUND_POSITION_OR_MODE_SET.getMessageType(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_SET.getMessageType(),
new byte[]{
PayloadType.SOUND_POSITION_OR_MODE_SET.getCode(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_SET.getCode(),
VirtualSoundParam.SOUND_POSITION.getCode(),
config.getCode()
}
@ -348,9 +347,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getSurroundMode() {
return new Request(
PayloadType.SOUND_POSITION_OR_MODE_GET.getMessageType(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_GET.getMessageType(),
new byte[]{
PayloadType.SOUND_POSITION_OR_MODE_GET.getCode(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_GET.getCode(),
VirtualSoundParam.SURROUND_MODE.getCode()
}
);
@ -359,9 +358,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setSurroundMode(final SurroundMode config) {
return new Request(
PayloadType.SOUND_POSITION_OR_MODE_SET.getMessageType(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_SET.getMessageType(),
new byte[]{
PayloadType.SOUND_POSITION_OR_MODE_SET.getCode(),
PayloadTypeV1.SOUND_POSITION_OR_MODE_SET.getCode(),
VirtualSoundParam.SURROUND_MODE.getCode(),
config.getCode()
}
@ -371,9 +370,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getTouchSensor() {
return new Request(
PayloadType.TOUCH_SENSOR_GET.getMessageType(),
PayloadTypeV1.TOUCH_SENSOR_GET.getMessageType(),
new byte[]{
PayloadType.TOUCH_SENSOR_GET.getCode(),
PayloadTypeV1.TOUCH_SENSOR_GET.getCode(),
(byte) 0xd2
}
);
@ -382,9 +381,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setTouchSensor(final TouchSensor config) {
return new Request(
PayloadType.TOUCH_SENSOR_SET.getMessageType(),
PayloadTypeV1.TOUCH_SENSOR_SET.getMessageType(),
new byte[]{
PayloadType.TOUCH_SENSOR_SET.getCode(),
PayloadTypeV1.TOUCH_SENSOR_SET.getCode(),
(byte) 0xd2,
(byte) 0x01,
(byte) (config.isEnabled() ? 0x01 : 0x00)
@ -395,9 +394,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request getVoiceNotifications() {
return new Request(
PayloadType.VOICE_NOTIFICATIONS_GET.getMessageType(),
PayloadTypeV1.VOICE_NOTIFICATIONS_GET.getMessageType(),
new byte[]{
PayloadType.VOICE_NOTIFICATIONS_GET.getCode(),
PayloadTypeV1.VOICE_NOTIFICATIONS_GET.getCode(),
(byte) 0x01,
(byte) 0x01
}
@ -407,9 +406,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request setVoiceNotifications(final VoiceNotifications config) {
return new Request(
PayloadType.VOICE_NOTIFICATIONS_SET.getMessageType(),
PayloadTypeV1.VOICE_NOTIFICATIONS_SET.getMessageType(),
new byte[]{
PayloadType.VOICE_NOTIFICATIONS_SET.getCode(),
PayloadTypeV1.VOICE_NOTIFICATIONS_SET.getCode(),
(byte) 0x01,
(byte) 0x01,
(byte) (config.isEnabled() ? 0x01 : 0x00)
@ -420,9 +419,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request startNoiseCancellingOptimizer(final boolean start) {
return new Request(
PayloadType.NOISE_CANCELLING_OPTIMIZER_START.getMessageType(),
PayloadTypeV1.NOISE_CANCELLING_OPTIMIZER_START.getMessageType(),
new byte[]{
PayloadType.NOISE_CANCELLING_OPTIMIZER_START.getCode(),
PayloadTypeV1.NOISE_CANCELLING_OPTIMIZER_START.getCode(),
(byte) 0x01,
(byte) 0x00,
(byte) (start ? 0x01 : 0x00)
@ -433,9 +432,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public Request powerOff() {
return new Request(
PayloadType.POWER_OFF.getMessageType(),
PayloadTypeV1.POWER_OFF.getMessageType(),
new byte[]{
PayloadType.POWER_OFF.getCode(),
PayloadTypeV1.POWER_OFF.getCode(),
(byte) 0x00,
(byte) 0x01
}
@ -444,7 +443,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
@Override
public List<? extends GBDeviceEvent> handlePayload(final MessageType messageType, final byte[] payload) {
final PayloadType payloadType = PayloadType.fromCode(messageType, payload[0]);
final PayloadTypeV1 payloadType = PayloadTypeV1.fromCode(messageType, payload[0]);
switch (payloadType) {
case INIT_REPLY:
@ -493,12 +492,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
}
public List<? extends GBDeviceEvent> handleInitResponse(final byte[] payload) {
if (payload.length != 4) {
LOG.warn("Unexpected payload length {}", payload.length);
return Collections.emptyList();
}
final SonyHeadphonesCoordinator coordinator = (SonyHeadphonesCoordinator) DeviceHelper.getInstance().getCoordinator(getDevice());
final SonyHeadphonesCoordinator coordinator = getCoordinator();
// Populate the init requests
final List<Request> capabilityRequests = new ArrayList<>();
@ -530,6 +524,9 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
}
}
// Remove any requests that are not supported by other protocol version
capabilityRequests.removeAll(Collections.singleton(null));
return Collections.singletonList(new SonyHeadphonesEnqueueRequestEvent(capabilityRequests));
}
@ -570,17 +567,10 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
boolean focusOnVoice;
switch (payload[6]) {
case 0x00:
focusOnVoice = false;
break;
case 0x01:
focusOnVoice = true;
break;
default:
LOG.warn("Unknown focus on voice mode {}", String.format("%02x", payload[6]));
return Collections.emptyList();
final Boolean focusOnVoice = booleanFromByte(payload[6]);
if (focusOnVoice == null) {
LOG.warn("Unknown focus on voice mode {}", String.format("%02x", payload[6]));
return Collections.emptyList();
}
int ambientSound = payload[7];
@ -606,7 +596,6 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
}
final NoiseCancellingOptimizerStatus status = NoiseCancellingOptimizerStatus.fromCode(payload[3]);
if (status == null) {
LOG.warn("Unable to determine noise cancelling opptimizer status from {}", GB.hexdump(payload));
return Collections.emptyList();
@ -649,18 +638,10 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
boolean enabled;
switch (payload[3]) {
case 0x00:
enabled = false;
break;
case 0x01:
enabled = true;
break;
default:
LOG.warn("Unknown audio upsampling code {}", String.format("%02x", payload[3]));
return Collections.emptyList();
final Boolean enabled = booleanFromByte(payload[3]);
if (enabled == null) {
LOG.warn("Unknown audio upsampling code {}", String.format("%02x", payload[3]));
return Collections.emptyList();
}
LOG.debug("Audio Upsampling: {}", enabled);
@ -683,15 +664,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
AutomaticPowerOff mode = null;
for (AutomaticPowerOff value : AutomaticPowerOff.values()) {
if (value.getCode()[0] == payload[3] && value.getCode()[1] == payload[4]) {
mode = value;
break;
}
}
final AutomaticPowerOff mode = AutomaticPowerOff.fromCode(payload[3], payload[4]);
if (mode == null) {
LOG.warn("Unknown automatic power off codes {}", String.format("%02x %02x", payload[3], payload[4]));
return Collections.emptyList();
@ -711,22 +684,8 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
ButtonModes.Mode modeLeft = null;
for (ButtonModes.Mode value : ButtonModes.Mode.values()) {
if (value.getCode() == payload[3]) {
modeLeft = value;
break;
}
}
ButtonModes.Mode modeRight = null;
for (ButtonModes.Mode value : ButtonModes.Mode.values()) {
if (value.getCode() == payload[4]) {
modeRight = value;
break;
}
}
final ButtonModes.Mode modeLeft = ButtonModes.Mode.fromCode(payload[3]);
final ButtonModes.Mode modeRight = ButtonModes.Mode.fromCode(payload[4]);
if (modeLeft == null || modeRight == null) {
LOG.warn("Unknown button mode codes {}", String.format("%02x %02x", payload[3], payload[4]));
return Collections.emptyList();
@ -746,21 +705,13 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
boolean enabled;
switch (payload[3]) {
case 0x00:
enabled = false;
break;
case 0x01:
enabled = true;
break;
default:
LOG.warn("Unknown pause when taken off code {}", String.format("%02x", payload[3]));
return Collections.emptyList();
final Boolean enabled = booleanFromByte(payload[3]);
if (enabled == null) {
LOG.warn("Unknown pause when taken off code {}", String.format("%02x", payload[3]));
return Collections.emptyList();
}
LOG.debug("Touch Sensor: {}", enabled);
LOG.debug("Pause when taken off: {}", enabled);
final GBDeviceEventUpdatePreferences event = new GBDeviceEventUpdatePreferences()
.withPreferences(new PauseWhenTakenOff(enabled).toPreferences());
@ -769,7 +720,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
}
public List<? extends GBDeviceEvent> handleBattery(final byte[] payload) {
final BatteryType batteryType = BatteryType.fromCode(payload[1]);
final BatteryType batteryType = decodeBatteryType(payload[1]);
if (batteryType == null) {
LOG.warn("Unknown battery type code {}", String.format("%02x", payload[1]));
@ -822,8 +773,12 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
final AudioCodec audioCodec = AudioCodec.fromCode(payload[2]);
if (payload[1] != 0x00) {
LOG.warn("Not audio codec, ignoring");
return Collections.emptyList();
}
final AudioCodec audioCodec = AudioCodec.fromCode(payload[2]);
if (audioCodec == null) {
LOG.warn("Unable to determine audio codec from {}", GB.hexdump(payload));
return Collections.emptyList();
@ -843,14 +798,7 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.emptyList();
}
EqualizerPreset mode = null;
for (EqualizerPreset value : EqualizerPreset.values()) {
if (value.getCode() == payload[2]) {
mode = value;
break;
}
}
final EqualizerPreset mode = EqualizerPreset.fromCode(payload[2]);
if (mode == null) {
LOG.warn("Unknown equalizer preset code {}", String.format("%02x", payload[2]));
return Collections.emptyList();
@ -879,6 +827,11 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
public List<? extends GBDeviceEvent> handleFirmwareVersion(final byte[] payload) {
final Pattern VERSION_REGEX = Pattern.compile("^[0-9.\\-a-zA-Z_]+$");
if (payload[1] != 0x02) {
LOG.warn("Not firmware version, ignoring");
return Collections.emptyList();
}
if (payload.length < 4) {
LOG.warn("Unexpected payload length {}", payload.length);
return Collections.emptyList();
@ -886,6 +839,12 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
final String firmwareVersion = new String(Arrays.copyOfRange(payload, 3, payload.length));
final int expectedLength = payload[2] & 0xff;
if (firmwareVersion.length() != expectedLength) {
LOG.warn("Unexpected firmware version length {}, expected {}", firmwareVersion.length(), expectedLength);
return Collections.emptyList();
}
if (!VERSION_REGEX.matcher(firmwareVersion).find()) {
LOG.warn("Unexpected characters in version '{}'", firmwareVersion);
return Collections.emptyList();
@ -1060,9 +1019,47 @@ public class SonyProtocolImplV1 extends AbstractSonyProtocolImpl {
return Collections.singletonList(event);
}
private boolean supportsWindNoiseCancelling() {
final SonyHeadphonesCoordinator coordinator = (SonyHeadphonesCoordinator) DeviceHelper.getInstance().getCoordinator(getDevice());
protected Boolean booleanFromByte(final byte b) {
switch (b) {
case 0x00:
return false;
case 0x01:
return true;
default:
}
return null;
}
protected boolean supportsWindNoiseCancelling() {
final SonyHeadphonesCoordinator coordinator = getCoordinator();
return coordinator.supports(SonyHeadphonesCapabilities.WindNoiseReduction);
}
protected BatteryType decodeBatteryType(final byte b) {
switch (b) {
case 0x00:
return BatteryType.SINGLE;
case 0x01:
return BatteryType.DUAL;
case 0x02:
return BatteryType.CASE;
}
return null;
}
protected byte encodeBatteryType(final BatteryType batteryType) {
switch (batteryType) {
case SINGLE:
return 0x00;
case DUAL:
return 0x01;
case CASE:
return 0x02;
}
throw new IllegalArgumentException("Unknown battery type " + batteryType);
}
}

View File

@ -38,6 +38,12 @@ public enum NoiseCancellingOptimizerStatus {
return this.code;
}
public String i18n(final Context context) {
final String stringName = String.format("sony_anc_optimizer_status_%s", name().toLowerCase(Locale.ROOT));
final int stringId = context.getResources().getIdentifier(stringName, "string", context.getPackageName());
return context.getString(stringId);
}
public static NoiseCancellingOptimizerStatus fromCode(final byte code) {
for (final NoiseCancellingOptimizerStatus audioCodec : values()) {
if (audioCodec.code == code) {
@ -47,10 +53,4 @@ public enum NoiseCancellingOptimizerStatus {
return null;
}
public String i18n(final Context context) {
final String stringName = String.format("sony_anc_optimizer_status_%s", name().toLowerCase(Locale.ROOT));
final int stringId = context.getResources().getIdentifier(stringName, "string", context.getPackageName());
return context.getString(stringId);
}
}