1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-01 14:32:54 +01:00

Sony WH-1000XM3: Simplify protocol code

This commit is contained in:
José Rebelo 2021-11-16 22:17:44 +00:00
parent d2fe8e5607
commit 6db775a9df
6 changed files with 117 additions and 235 deletions

View File

@ -18,4 +18,11 @@ package nodomain.freeyourgadget.gadgetbridge.deviceevents;
public class GBDeviceEventSendBytes extends GBDeviceEvent { public class GBDeviceEventSendBytes extends GBDeviceEvent {
public byte[] encodedBytes; public byte[] encodedBytes;
public GBDeviceEventSendBytes() {
}
public GBDeviceEventSendBytes(final byte[] encodedBytes) {
this.encodedBytes = encodedBytes;
}
} }

View File

@ -17,9 +17,15 @@
package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3; package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3;
public enum AutomaticPowerOff { public enum AutomaticPowerOff {
OFF, OFF(new byte[]{(byte) 0x11, (byte) 0x00}),
AFTER_5_MIN, AFTER_5_MIN(new byte[]{(byte) 0x00, (byte) 0x00}),
AFTER_30_MIN, AFTER_30_MIN(new byte[]{(byte) 0x01, (byte) 0x01}),
AFTER_1_HOUR, AFTER_1_HOUR(new byte[]{(byte) 0x02, (byte) 0x02}),
AFTER_3_HOUR AFTER_3_HOUR(new byte[]{(byte) 0x03, (byte) 0x03});
public final byte[] code;
AutomaticPowerOff(final byte[] code) {
this.code = code;
}
} }

View File

@ -17,16 +17,22 @@
package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3; package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3;
public enum EqualizerPreset { public enum EqualizerPreset {
OFF, OFF(new byte[] {(byte) 0x00, (byte) 0x00}),
BRIGHT, BRIGHT(new byte[] {(byte) 0x10, (byte) 0x00}),
EXCITED, EXCITED(new byte[] {(byte) 0x11, (byte) 0x00}),
MELLOW, MELLOW(new byte[] {(byte) 0x12, (byte) 0x00}),
RELAXED, RELAXED(new byte[] {(byte) 0x13, (byte) 0x00}),
VOCAL, VOCAL(new byte[] {(byte) 0x14, (byte) 0x00}),
TREBLE_BOOST, TREBLE_BOOST(new byte[] {(byte) 0x15, (byte) 0x00}),
BASS_BOOST, BASS_BOOST(new byte[] {(byte) 0x16, (byte) 0x00}),
SPEECH, SPEECH(new byte[] {(byte) 0x17, (byte) 0x00}),
MANUAL, MANUAL(new byte[] {(byte) 0xa0, (byte) 0x00}),
CUSTOM_1, CUSTOM_1(new byte[] {(byte) 0xa1, (byte) 0x00}),
CUSTOM_2 CUSTOM_2(new byte[] {(byte) 0xa2, (byte) 0x00});
public final byte[] code;
EqualizerPreset(final byte[] code) {
this.code = code;
}
} }

View File

@ -17,10 +17,16 @@
package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3; package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3;
public enum SoundPosition { public enum SoundPosition {
OFF, OFF((byte) 0x00),
FRONT, FRONT((byte) 0x03),
FRONT_LEFT, FRONT_LEFT((byte) 0x01),
FRONT_RIGHT, FRONT_RIGHT((byte) 0x02),
REAR_LEFT, REAR_LEFT((byte) 0x11),
REAR_RIGHT REAR_RIGHT((byte) 0x12);
public final byte code;
SoundPosition(final byte code) {
this.code = code;
}
} }

View File

@ -17,9 +17,15 @@
package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3; package nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3;
public enum SurroundMode { public enum SurroundMode {
OFF, OFF((byte) 0x00),
ARENA, ARENA((byte) 0x02),
CLUB, CLUB((byte) 0x04),
OUTDOOR_STAGE, OUTDOOR_STAGE((byte) 0x01),
CONCERT_HALL CONCERT_HALL((byte) 0x03);
public final byte code;
SurroundMode(final byte code) {
this.code = code;
}
} }

View File

@ -30,6 +30,7 @@ import java.util.Arrays;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst; import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent; import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.AmbientSoundControl; import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.AmbientSoundControl;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.AutomaticPowerOff; import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.AutomaticPowerOff;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.EqualizerCustomBands; import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.EqualizerCustomBands;
@ -45,7 +46,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
/** /**
* Packet format: * Packet format:
* * <p>
* - PACKET_HEADER * - PACKET_HEADER
* - Command type? - almost always 0x0c? * - Command type? - almost always 0x0c?
* - Sequence Number - needs to be updated with the one sent in the responses * - Sequence Number - needs to be updated with the one sent in the responses
@ -53,7 +54,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
* - N bytes of data * - N bytes of data
* - Checksum (1-byte sum, excluding header) * - Checksum (1-byte sum, excluding header)
* - PACKET_TRAILER * - PACKET_TRAILER
* * <p>
* Data between PACKET_HEADER and PACKET_TRAILER is escaped with PACKET_ESCAPE, and the * Data between PACKET_HEADER and PACKET_TRAILER is escaped with PACKET_ESCAPE, and the
* following byte masked with PACKET_ESCAPE_MASK. * following byte masked with PACKET_ESCAPE_MASK.
*/ */
@ -68,7 +69,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
private static final byte CMD_SOUND_SURROUND = 0x01; private static final byte CMD_SOUND_SURROUND = 0x01;
private static final byte CMD_SOUND_POSITION = 0x02; private static final byte CMD_SOUND_POSITION = 0x02;
private int sequenceNumber = 0; private byte sequenceNumber = 0;
public SonyWh1000Xm3Protocol(GBDevice device) { public SonyWh1000Xm3Protocol(GBDevice device) {
super(device); super(device);
@ -104,7 +105,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
LOG.warn("Unknown message: {}", hexdump); LOG.warn("Unknown message: {}", hexdump);
return null; return new GBDeviceEvent[]{new GBDeviceEventSendBytes(encodeAck())};
} }
@Override @Override
@ -212,23 +213,21 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
return super.encodeSendConfiguration(config); return super.encodeSendConfiguration(config);
} }
public byte[] encodeAck() {
return encodeMessage(
MSG_TYPE_ACK,
new byte[]{}
);
}
public byte[] encodeTriggerNoiseCancellingOptimizer() { public byte[] encodeTriggerNoiseCancellingOptimizer() {
// This successfully triggers the noise cancelling optimizer. However, we don't get the // This successfully triggers the noise cancelling optimizer. However, we don't get the
// optimization progress messages. // optimization progress messages.
ByteBuffer buf = ByteBuffer.allocate(10); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0x84, (byte) 0x01, (byte) 0x00, (byte) 0x01}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(4);
buf.put((byte) 0x84);
buf.put((byte) 0x01);
buf.put((byte) 0x00);
buf.put((byte) 0x01);
return encodeMessage(buf.array());
} }
private byte[] encodeSoundControl(AmbientSoundControl ambientSoundControl, boolean focusOnVoice, int ambientSound) { private byte[] encodeSoundControl(AmbientSoundControl ambientSoundControl, boolean focusOnVoice, int ambientSound) {
@ -240,7 +239,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
buf.put((byte) 0x0c); buf.put((byte) 0x0c);
buf.put((byte) sequenceNumber++); buf.put(sequenceNumber++);
buf.putInt(8); buf.putInt(8);
buf.put((byte) 0x68); buf.put((byte) 0x68);
@ -274,123 +273,24 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
} }
private byte[] encodeSoundPosition(SoundPosition position) { private byte[] encodeSoundPosition(SoundPosition position) {
final ByteBuffer buf = ByteBuffer.allocate(9); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0x48, CMD_SOUND_POSITION, position.code}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(3);
buf.put((byte) 0x48);
buf.put(CMD_SOUND_POSITION);
switch (position) {
case OFF:
buf.put((byte) 0x00);
break;
case FRONT:
buf.put((byte) 0x03);
break;
case FRONT_LEFT:
buf.put((byte) 0x01);
break;
case FRONT_RIGHT:
buf.put((byte) 0x02);
break;
case REAR_LEFT:
buf.put((byte) 0x11);
break;
case REAR_RIGHT:
buf.put((byte) 0x12);
break;
}
return encodeMessage(buf.array());
} }
private byte[] encodeSurroundMode(SurroundMode mode) { private byte[] encodeSurroundMode(SurroundMode mode) {
final ByteBuffer buf = ByteBuffer.allocate(9); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0x48, CMD_SOUND_SURROUND, mode.code}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(3);
buf.put((byte) 0x48);
buf.put(CMD_SOUND_SURROUND);
switch (mode) {
case OFF:
buf.put((byte) 0x00);
break;
case ARENA:
buf.put((byte) 0x02);
break;
case CLUB:
buf.put((byte) 0x04);
break;
case OUTDOOR_STAGE:
buf.put((byte) 0x01);
break;
case CONCERT_HALL:
buf.put((byte) 0x03);
break;
}
return encodeMessage(buf.array());
} }
private byte[] encodeEqualizerPreset(EqualizerPreset preset) { private byte[] encodeEqualizerPreset(EqualizerPreset preset) {
final ByteBuffer buf = ByteBuffer.allocate(10); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0x58, (byte) 0x01, preset.code[0], preset.code[1]}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(4);
buf.put((byte) 0x58);
buf.put((byte) 0x01);
switch (preset) {
case OFF:
buf.put((byte) 0x00).put((byte) 0x00);
break;
case BRIGHT:
buf.put((byte) 0x10).put((byte) 0x00);
break;
case EXCITED:
buf.put((byte) 0x11).put((byte) 0x00);
break;
case MELLOW:
buf.put((byte) 0x12).put((byte) 0x00);
break;
case RELAXED:
buf.put((byte) 0x13).put((byte) 0x00);
break;
case VOCAL:
buf.put((byte) 0x14).put((byte) 0x00);
break;
case TREBLE_BOOST:
buf.put((byte) 0x15).put((byte) 0x00);
break;
case BASS_BOOST:
buf.put((byte) 0x16).put((byte) 0x00);
break;
case SPEECH:
buf.put((byte) 0x17).put((byte) 0x00);
break;
case MANUAL:
buf.put((byte) 0xa0).put((byte) 0x00);
break;
case CUSTOM_1:
buf.put((byte) 0xa1).put((byte) 0x00);
break;
case CUSTOM_2:
buf.put((byte) 0xa2).put((byte) 0x00);
break;
}
return encodeMessage(buf.array());
} }
private byte[] encodeEqualizerCustomBands(EqualizerPreset preset, EqualizerPreset previousPreset, EqualizerCustomBands equalizer) { private byte[] encodeEqualizerCustomBands(EqualizerPreset preset, EqualizerPreset previousPreset, EqualizerCustomBands equalizer) {
@ -403,12 +303,6 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
} }
cmdStream.write(encodeEqualizerCustomBands(equalizer)); cmdStream.write(encodeEqualizerCustomBands(equalizer));
if (preset != previousPreset) {
// And then we swap back to the previous preset
// FIXME: this is not working, the new preset stays
//cmdStream.write(encodeEqualizerPreset(previousPreset));
}
} catch (IOException e) { } catch (IOException e) {
LOG.error("This should never happen", e); LOG.error("This should never happen", e);
} }
@ -417,12 +311,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
} }
private byte[] encodeEqualizerCustomBands(EqualizerCustomBands equalizer) { private byte[] encodeEqualizerCustomBands(EqualizerCustomBands equalizer) {
final ByteBuffer buf = ByteBuffer.allocate(16); final ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.BIG_ENDIAN);
buf.put((byte) 0x0c);
buf.put((byte) sequenceNumber++);
buf.putInt(10);
buf.put((byte) 0x58); buf.put((byte) 0x58);
buf.put((byte) 0x01); buf.put((byte) 0x01);
@ -434,86 +323,48 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
buf.put((byte) (band + 10)); buf.put((byte) (band + 10));
} }
return encodeMessage(buf.array()); return encodeMessage(
(byte) 0x0c,
buf.array()
);
} }
private byte[] encodeDSEEHX(boolean enabled) { private byte[] encodeDSEEHX(boolean enabled) {
ByteBuffer buf = ByteBuffer.allocate(10); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0xe8, (byte) 0x02, (byte) 0x00, (byte) (enabled ? 0x01 : 0x00)}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(4);
buf.put((byte) 0xe8);
buf.put((byte) 0x02);
buf.put((byte) 0x00);
buf.put((byte) (enabled ? 0x01 : 0x00));
return encodeMessage(buf.array());
} }
private byte[] encodeTouchSensor(boolean enabled) { private byte[] encodeTouchSensor(boolean enabled) {
ByteBuffer buf = ByteBuffer.allocate(10); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0xd8, (byte) 0xd2, (byte) 0x01, (byte) (enabled ? 0x01 : 0x00)}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(4);
buf.put((byte) 0xd8);
buf.put((byte) 0xd2);
buf.put((byte) 0x01);
buf.put((byte) (enabled ? 0x01 : 0x00));
return encodeMessage(buf.array());
} }
private byte[] encodeAutomaticPowerOff(AutomaticPowerOff automaticPowerOff) { private byte[] encodeAutomaticPowerOff(AutomaticPowerOff automaticPowerOff) {
ByteBuffer buf = ByteBuffer.allocate(11); return encodeMessage(
buf.order(ByteOrder.BIG_ENDIAN); (byte) 0x0c,
new byte[]{(byte) 0xf8, (byte) 0x04, (byte) 0x01, automaticPowerOff.code[0], automaticPowerOff.code[1]}
buf.put((byte) 0x0c); );
buf.put((byte) sequenceNumber++);
buf.putInt(5);
buf.put((byte) 0xf8);
buf.put((byte) 0x04);
buf.put((byte) 0x01);
switch (automaticPowerOff) {
case OFF:
buf.put((byte) 0x11).put((byte) 0x00);
break;
case AFTER_5_MIN:
buf.put((byte) 0x00).put((byte) 0x00);
break;
case AFTER_30_MIN:
buf.put((byte) 0x01).put((byte) 0x01);
break;
case AFTER_1_HOUR:
buf.put((byte) 0x02).put((byte) 0x02);
break;
case AFTER_3_HOUR:
buf.put((byte) 0x03).put((byte) 0x03);
break;
}
return encodeMessage(buf.array());
} }
private byte[] encodeVoiceNotifications(boolean enabled) { private byte[] encodeVoiceNotifications(boolean enabled) {
ByteBuffer buf = ByteBuffer.allocate(10); return encodeMessage(
(byte) 0x0e,
new byte[]{(byte) 0x48, (byte) 0x01, (byte) 0x01, (byte) (enabled ? 0x01 : 0x00)}
);
}
private byte[] encodeMessage(byte type, byte[] content) {
ByteBuffer buf = ByteBuffer.allocate(content.length + 6);
buf.order(ByteOrder.BIG_ENDIAN); buf.order(ByteOrder.BIG_ENDIAN);
buf.put((byte) 0x0e); buf.put(type);
buf.put((byte) sequenceNumber++); buf.put(sequenceNumber++);
buf.putInt(4); buf.putInt(content.length);
buf.put(content);
buf.put((byte) 0x48);
buf.put((byte) 0x01);
buf.put((byte) 0x01);
buf.put((byte) (enabled ? 0x01 : 0x00));
return encodeMessage(buf.array()); return encodeMessage(buf.array());
} }