1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-29 13:26:50 +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 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;
public enum AutomaticPowerOff {
OFF,
AFTER_5_MIN,
AFTER_30_MIN,
AFTER_1_HOUR,
AFTER_3_HOUR
OFF(new byte[]{(byte) 0x11, (byte) 0x00}),
AFTER_5_MIN(new byte[]{(byte) 0x00, (byte) 0x00}),
AFTER_30_MIN(new byte[]{(byte) 0x01, (byte) 0x01}),
AFTER_1_HOUR(new byte[]{(byte) 0x02, (byte) 0x02}),
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;
public enum EqualizerPreset {
OFF,
BRIGHT,
EXCITED,
MELLOW,
RELAXED,
VOCAL,
TREBLE_BOOST,
BASS_BOOST,
SPEECH,
MANUAL,
CUSTOM_1,
CUSTOM_2
OFF(new byte[] {(byte) 0x00, (byte) 0x00}),
BRIGHT(new byte[] {(byte) 0x10, (byte) 0x00}),
EXCITED(new byte[] {(byte) 0x11, (byte) 0x00}),
MELLOW(new byte[] {(byte) 0x12, (byte) 0x00}),
RELAXED(new byte[] {(byte) 0x13, (byte) 0x00}),
VOCAL(new byte[] {(byte) 0x14, (byte) 0x00}),
TREBLE_BOOST(new byte[] {(byte) 0x15, (byte) 0x00}),
BASS_BOOST(new byte[] {(byte) 0x16, (byte) 0x00}),
SPEECH(new byte[] {(byte) 0x17, (byte) 0x00}),
MANUAL(new byte[] {(byte) 0xa0, (byte) 0x00}),
CUSTOM_1(new byte[] {(byte) 0xa1, (byte) 0x00}),
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;
public enum SoundPosition {
OFF,
FRONT,
FRONT_LEFT,
FRONT_RIGHT,
REAR_LEFT,
REAR_RIGHT
OFF((byte) 0x00),
FRONT((byte) 0x03),
FRONT_LEFT((byte) 0x01),
FRONT_RIGHT((byte) 0x02),
REAR_LEFT((byte) 0x11),
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;
public enum SurroundMode {
OFF,
ARENA,
CLUB,
OUTDOOR_STAGE,
CONCERT_HALL
OFF((byte) 0x00),
ARENA((byte) 0x02),
CLUB((byte) 0x04),
OUTDOOR_STAGE((byte) 0x01),
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.activities.devicesettings.DeviceSettingsPreferenceConst;
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.AutomaticPowerOff;
import nodomain.freeyourgadget.gadgetbridge.devices.sony.wh1000xm3.EqualizerCustomBands;
@ -45,7 +46,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
/**
* Packet format:
*
* <p>
* - PACKET_HEADER
* - Command type? - almost always 0x0c?
* - 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
* - Checksum (1-byte sum, excluding header)
* - PACKET_TRAILER
*
* <p>
* Data between PACKET_HEADER and PACKET_TRAILER is escaped with PACKET_ESCAPE, and the
* 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_POSITION = 0x02;
private int sequenceNumber = 0;
private byte sequenceNumber = 0;
public SonyWh1000Xm3Protocol(GBDevice device) {
super(device);
@ -104,7 +105,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
LOG.warn("Unknown message: {}", hexdump);
return null;
return new GBDeviceEvent[]{new GBDeviceEventSendBytes(encodeAck())};
}
@Override
@ -212,23 +213,21 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
return super.encodeSendConfiguration(config);
}
public byte[] encodeAck() {
return encodeMessage(
MSG_TYPE_ACK,
new byte[]{}
);
}
public byte[] encodeTriggerNoiseCancellingOptimizer() {
// This successfully triggers the noise cancelling optimizer. However, we don't get the
// optimization progress messages.
ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0x84, (byte) 0x01, (byte) 0x00, (byte) 0x01}
);
}
private byte[] encodeSoundControl(AmbientSoundControl ambientSoundControl, boolean focusOnVoice, int ambientSound) {
@ -240,7 +239,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
buf.order(ByteOrder.BIG_ENDIAN);
buf.put((byte) 0x0c);
buf.put((byte) sequenceNumber++);
buf.put(sequenceNumber++);
buf.putInt(8);
buf.put((byte) 0x68);
@ -274,123 +273,24 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
}
private byte[] encodeSoundPosition(SoundPosition position) {
final ByteBuffer buf = ByteBuffer.allocate(9);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0x48, CMD_SOUND_POSITION, position.code}
);
}
private byte[] encodeSurroundMode(SurroundMode mode) {
final ByteBuffer buf = ByteBuffer.allocate(9);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0x48, CMD_SOUND_SURROUND, mode.code}
);
}
private byte[] encodeEqualizerPreset(EqualizerPreset preset) {
final ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0x58, (byte) 0x01, preset.code[0], preset.code[1]}
);
}
private byte[] encodeEqualizerCustomBands(EqualizerPreset preset, EqualizerPreset previousPreset, EqualizerCustomBands equalizer) {
@ -403,12 +303,6 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
}
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) {
LOG.error("This should never happen", e);
}
@ -417,12 +311,7 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
}
private byte[] encodeEqualizerCustomBands(EqualizerCustomBands equalizer) {
final ByteBuffer buf = ByteBuffer.allocate(16);
buf.order(ByteOrder.BIG_ENDIAN);
buf.put((byte) 0x0c);
buf.put((byte) sequenceNumber++);
buf.putInt(10);
final ByteBuffer buf = ByteBuffer.allocate(10);
buf.put((byte) 0x58);
buf.put((byte) 0x01);
@ -434,86 +323,48 @@ public class SonyWh1000Xm3Protocol extends GBDeviceProtocol {
buf.put((byte) (band + 10));
}
return encodeMessage(buf.array());
return encodeMessage(
(byte) 0x0c,
buf.array()
);
}
private byte[] encodeDSEEHX(boolean enabled) {
ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0xe8, (byte) 0x02, (byte) 0x00, (byte) (enabled ? 0x01 : 0x00)}
);
}
private byte[] encodeTouchSensor(boolean enabled) {
ByteBuffer buf = ByteBuffer.allocate(10);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0xd8, (byte) 0xd2, (byte) 0x01, (byte) (enabled ? 0x01 : 0x00)}
);
}
private byte[] encodeAutomaticPowerOff(AutomaticPowerOff automaticPowerOff) {
ByteBuffer buf = ByteBuffer.allocate(11);
buf.order(ByteOrder.BIG_ENDIAN);
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());
return encodeMessage(
(byte) 0x0c,
new byte[]{(byte) 0xf8, (byte) 0x04, (byte) 0x01, automaticPowerOff.code[0], automaticPowerOff.code[1]}
);
}
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.put((byte) 0x0e);
buf.put((byte) sequenceNumber++);
buf.putInt(4);
buf.put((byte) 0x48);
buf.put((byte) 0x01);
buf.put((byte) 0x01);
buf.put((byte) (enabled ? 0x01 : 0x00));
buf.put(type);
buf.put(sequenceNumber++);
buf.putInt(content.length);
buf.put(content);
return encodeMessage(buf.array());
}