mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-09-27 08:47:03 +02:00
Soundcore: Cleanup Code
This commit is contained in:
parent
545603f58c
commit
ea079c2467
@ -18,26 +18,19 @@ import java.util.UUID;
|
|||||||
|
|
||||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
|
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
|
|
||||||
|
|
||||||
public class SoundcoreLibertyIOThread extends BtClassicIoThread {
|
public class SoundcoreLibertyIOThread extends BtClassicIoThread {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreLibertyIOThread.class);
|
private static final Logger LOG = LoggerFactory.getLogger(SoundcoreLibertyIOThread.class);
|
||||||
private final SoundcoreLibertyProtocol mSoundcoreProtocol;
|
private final SoundcoreLibertyProtocol mSoundcoreProtocol;
|
||||||
private final SoundcoreLiberty3ProDeviceSupport mDeviceSupport;
|
|
||||||
|
|
||||||
public SoundcoreLibertyIOThread(GBDevice gbDevice, Context context, SoundcoreLibertyProtocol deviceProtocol, SoundcoreLiberty3ProDeviceSupport deviceSupport, BluetoothAdapter btAdapter) {
|
public SoundcoreLibertyIOThread(GBDevice gbDevice, Context context, SoundcoreLibertyProtocol deviceProtocol, SoundcoreLiberty3ProDeviceSupport deviceSupport, BluetoothAdapter btAdapter) {
|
||||||
super(gbDevice, context, deviceProtocol, deviceSupport, btAdapter);
|
super(gbDevice, context, deviceProtocol, deviceSupport, btAdapter);
|
||||||
mSoundcoreProtocol = deviceProtocol;
|
mSoundcoreProtocol = deviceProtocol;
|
||||||
mDeviceSupport = deviceSupport;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initialize() {
|
protected void initialize() {
|
||||||
// write(mSoundcoreProtocol.encodeBatteryStatusRequest());
|
|
||||||
// write(mSoundcoreProtocol.encodeAudioModeStatusReq());
|
|
||||||
write(mSoundcoreProtocol.encodeDeviceInfoRequest());
|
write(mSoundcoreProtocol.encodeDeviceInfoRequest());
|
||||||
// write(mSoundcoreProtocol.encodeMysteryDataRequest1());
|
|
||||||
// gbDevice.setBatteryLevel(mDeviceSupport.);
|
|
||||||
setUpdateState(GBDevice.State.INITIALIZED);
|
setUpdateState(GBDevice.State.INITIALIZED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,8 +39,6 @@ public class SoundcoreLibertyIOThread extends BtClassicIoThread {
|
|||||||
return mSoundcoreProtocol.UUID_DEVICE_CTRL;
|
return mSoundcoreProtocol.UUID_DEVICE_CTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected byte[] parseIncoming(InputStream inStream) throws IOException {
|
protected byte[] parseIncoming(InputStream inStream) throws IOException {
|
||||||
byte[] buffer = new byte[1048576]; //HUGE read
|
byte[] buffer = new byte[1048576]; //HUGE read
|
||||||
|
@ -38,11 +38,6 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
super(device);
|
super(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readString(byte[] data, int position, int size) {
|
|
||||||
if (position + size > data.length) throw new IllegalStateException();
|
|
||||||
return new String(data, position, size, StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GBDeviceEventBatteryInfo buildBatteryInfo(int batteryIndex, int level) {
|
private GBDeviceEventBatteryInfo buildBatteryInfo(int batteryIndex, int level) {
|
||||||
GBDeviceEventBatteryInfo info = new GBDeviceEventBatteryInfo();
|
GBDeviceEventBatteryInfo info = new GBDeviceEventBatteryInfo();
|
||||||
info.batteryIndex = batteryIndex;
|
info.batteryIndex = batteryIndex;
|
||||||
@ -58,6 +53,10 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String readString(byte[] data, int position, int size) {
|
||||||
|
if (position + size > data.length) throw new IllegalStateException();
|
||||||
|
return new String(data, position, size, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
|
||||||
// Byte 0-4: Header
|
// Byte 0-4: Header
|
||||||
@ -103,81 +102,7 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
return devEvts.toArray(new GBDeviceEvent[devEvts.size()]);
|
return devEvts.toArray(new GBDeviceEvent[devEvts.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void decodeAudioMode(byte[] payload) {
|
||||||
* Encodes the following settings to a payload to set the audio-mode on the headphones:
|
|
||||||
* PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL If ANC, Transparent or neither should be active
|
|
||||||
* PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING If the strenght of the ANC should be set manual or adaptively according to ambient noise
|
|
||||||
* PREF_SONY_AMBIENT_SOUND_LEVEL How strong the ANC should be in manual mode
|
|
||||||
* PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE If the Transparency should focus on vocals or should be fully transparent
|
|
||||||
* PREF_SOUNDCORE_WIND_NOISE_REDUCTION If Transparency or ANC should reduce Wind Noise
|
|
||||||
* @return The payload
|
|
||||||
*/
|
|
||||||
byte[] encodeAudioMode() {
|
|
||||||
Prefs prefs = getDevicePrefs();
|
|
||||||
|
|
||||||
byte anc_mode;
|
|
||||||
switch (prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off")) {
|
|
||||||
case "noise_cancelling":
|
|
||||||
anc_mode = 0x00;
|
|
||||||
break;
|
|
||||||
case "ambient_sound":
|
|
||||||
anc_mode = 0x01;
|
|
||||||
break;
|
|
||||||
case "off":
|
|
||||||
anc_mode = 0x02;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.error("Invalid Audio Mode selected");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte anc_strength;
|
|
||||||
switch (prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0)) {
|
|
||||||
case 0:
|
|
||||||
anc_strength = 0x10;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
anc_strength = 0x20;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
anc_strength = 0x30;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.error("Invalid ANC Strength selected");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte adaptive_anc = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true));
|
|
||||||
byte vocal_mode = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false));
|
|
||||||
byte windnoise_reduction = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false));
|
|
||||||
|
|
||||||
byte[] payload = new byte[]{0x00, anc_mode, anc_strength, vocal_mode, adaptive_anc, windnoise_reduction, 0x01};
|
|
||||||
return encodeMessage((byte) 0x06, (byte) 0x81, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
byte[] encodeMessage(byte command1, byte command2, byte[] payload) {
|
|
||||||
int size = 8 + payload.length + 1;
|
|
||||||
ByteBuffer msgBuf = ByteBuffer.allocate(size);
|
|
||||||
msgBuf.order(ByteOrder.BIG_ENDIAN);
|
|
||||||
msgBuf.put(new byte[] {0x08, (byte) 0xee, 0x00, 0x00, 0x00}); // header
|
|
||||||
msgBuf.put(command1);
|
|
||||||
msgBuf.put(command2);
|
|
||||||
msgBuf.put((byte) size);
|
|
||||||
|
|
||||||
msgBuf.put(payload);
|
|
||||||
|
|
||||||
byte checksum = -10;
|
|
||||||
checksum += command1 + command2 + size;
|
|
||||||
for (int b : payload) {
|
|
||||||
checksum += b;
|
|
||||||
}
|
|
||||||
msgBuf.put(checksum);
|
|
||||||
|
|
||||||
return msgBuf.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
void decodeAudioMode(byte[] payload) {
|
|
||||||
SharedPreferences prefs = getDevicePrefs().getPreferences();
|
SharedPreferences prefs = getDevicePrefs().getPreferences();
|
||||||
SharedPreferences.Editor editor = prefs.edit();
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
String soundmode = "off";
|
String soundmode = "off";
|
||||||
@ -211,30 +136,6 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] encodeDeviceInfoRequest() {
|
|
||||||
byte[] payload = new byte[]{0x00};
|
|
||||||
return encodeMessage((byte) 0x01, (byte) 0x01, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] encodeMysteryDataRequest1() {
|
|
||||||
byte[] payload = new byte[]{0x00, 0x00};
|
|
||||||
return encodeMessage((byte) 0x01, (byte) 0x8d, payload);
|
|
||||||
}
|
|
||||||
byte[] encodeMysteryDataRequest2() {
|
|
||||||
byte[] payload = new byte[]{0x00};
|
|
||||||
return encodeMessage((byte) 0x05, (byte) 0x01, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] encodeMysteryDataRequest3() {
|
|
||||||
byte[] payload = new byte[]{0x00, 0x00};
|
|
||||||
return encodeMessage((byte) 0x05, (byte) 0x82, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte encodeBoolean(boolean bool) {
|
|
||||||
if (bool) return 0x01;
|
|
||||||
else return 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] encodeSendConfiguration(String config) {
|
public byte[] encodeSendConfiguration(String config) {
|
||||||
Prefs prefs = getDevicePrefs();
|
Prefs prefs = getDevicePrefs();
|
||||||
@ -314,6 +215,76 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
return super.encodeSendConfiguration(config);
|
return super.encodeSendConfiguration(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
byte[] encodeDeviceInfoRequest() {
|
||||||
|
byte[] payload = new byte[]{0x00};
|
||||||
|
return encodeMessage((byte) 0x01, (byte) 0x01, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] encodeMysteryDataRequest1() {
|
||||||
|
byte[] payload = new byte[]{0x00, 0x00};
|
||||||
|
return encodeMessage((byte) 0x01, (byte) 0x8d, payload);
|
||||||
|
}
|
||||||
|
byte[] encodeMysteryDataRequest2() {
|
||||||
|
byte[] payload = new byte[]{0x00};
|
||||||
|
return encodeMessage((byte) 0x05, (byte) 0x01, payload);
|
||||||
|
}
|
||||||
|
byte[] encodeMysteryDataRequest3() {
|
||||||
|
byte[] payload = new byte[]{0x00, 0x00};
|
||||||
|
return encodeMessage((byte) 0x05, (byte) 0x82, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the following settings to a payload to set the audio-mode on the headphones:
|
||||||
|
* PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL If ANC, Transparent or neither should be active
|
||||||
|
* PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING If the strenght of the ANC should be set manual or adaptively according to ambient noise
|
||||||
|
* PREF_SONY_AMBIENT_SOUND_LEVEL How strong the ANC should be in manual mode
|
||||||
|
* PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE If the Transparency should focus on vocals or should be fully transparent
|
||||||
|
* PREF_SOUNDCORE_WIND_NOISE_REDUCTION If Transparency or ANC should reduce Wind Noise
|
||||||
|
* @return The payload
|
||||||
|
*/
|
||||||
|
private byte[] encodeAudioMode() {
|
||||||
|
Prefs prefs = getDevicePrefs();
|
||||||
|
|
||||||
|
byte anc_mode;
|
||||||
|
switch (prefs.getString(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_AMBIENT_SOUND_CONTROL, "off")) {
|
||||||
|
case "noise_cancelling":
|
||||||
|
anc_mode = 0x00;
|
||||||
|
break;
|
||||||
|
case "ambient_sound":
|
||||||
|
anc_mode = 0x01;
|
||||||
|
break;
|
||||||
|
case "off":
|
||||||
|
anc_mode = 0x02;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.error("Invalid Audio Mode selected");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte anc_strength;
|
||||||
|
switch (prefs.getInt(DeviceSettingsPreferenceConst.PREF_SONY_AMBIENT_SOUND_LEVEL, 0)) {
|
||||||
|
case 0:
|
||||||
|
anc_strength = 0x10;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
anc_strength = 0x20;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
anc_strength = 0x30;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG.error("Invalid ANC Strength selected");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte adaptive_anc = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_ADAPTIVE_NOISE_CANCELLING, true));
|
||||||
|
byte vocal_mode = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_TRANSPARENCY_VOCAL_MODE, false));
|
||||||
|
byte windnoise_reduction = encodeBoolean(prefs.getBoolean(DeviceSettingsPreferenceConst.PREF_SOUNDCORE_WIND_NOISE_REDUCTION, false));
|
||||||
|
|
||||||
|
byte[] payload = new byte[]{0x00, anc_mode, anc_strength, vocal_mode, adaptive_anc, windnoise_reduction, 0x01};
|
||||||
|
return encodeMessage((byte) 0x06, (byte) 0x81, payload);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables or disables a tap-action
|
* Enables or disables a tap-action
|
||||||
* @param action The byte that encodes the action (single/double/triple or long tap)
|
* @param action The byte that encodes the action (single/double/triple or long tap)
|
||||||
@ -337,7 +308,7 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
LOG.error("Invalid Tap action");
|
LOG.error("Invalid Tap action");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
payload = new byte[]{0x00, 0x00, action.code, enabled_byte};
|
payload = new byte[]{0x00, 0x00, action.getCode(), enabled_byte};
|
||||||
return encodeMessage((byte) 0x04, (byte) 0x83, payload);
|
return encodeMessage((byte) 0x04, (byte) 0x83, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,19 +324,19 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case SINGLE_TAP:
|
case SINGLE_TAP:
|
||||||
case DOUBLE_TAP:
|
case DOUBLE_TAP:
|
||||||
function_byte = (byte) (16*6 + function.code);
|
function_byte = (byte) (16*6 + function.getCode());
|
||||||
break;
|
break;
|
||||||
case TRIPLE_TAP:
|
case TRIPLE_TAP:
|
||||||
function_byte = (byte) (16*4 + function.code);
|
function_byte = (byte) (16*4 + function.getCode());
|
||||||
break;
|
break;
|
||||||
case LONG_PRESS:
|
case LONG_PRESS:
|
||||||
function_byte = (byte) (16*5 + function.code);
|
function_byte = (byte) (16*5 + function.getCode());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG.error("Invalid Tap action");
|
LOG.error("Invalid Tap action");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
byte[] payload = new byte[] {0x00, encodeBoolean(right), action.code, function_byte};
|
byte[] payload = new byte[] {0x00, encodeBoolean(right), action.getCode(), function_byte};
|
||||||
return encodeMessage((byte) 0x04, (byte) 0x81, payload);
|
return encodeMessage((byte) 0x04, (byte) 0x81, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,35 +350,29 @@ public class SoundcoreLibertyProtocol extends GBDeviceProtocol {
|
|||||||
return encodeMessage((byte) 0x06, (byte) 0x82, new byte[] {0x00, ambientModes});
|
return encodeMessage((byte) 0x06, (byte) 0x82, new byte[] {0x00, ambientModes});
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TapAction {
|
private byte encodeBoolean(boolean bool) {
|
||||||
SINGLE_TAP((byte) 0x02),
|
if (bool) return 0x01;
|
||||||
DOUBLE_TAP((byte) 0x00),
|
else return 0x00;
|
||||||
TRIPLE_TAP((byte) 0x05),
|
|
||||||
LONG_PRESS((byte) 0x01)
|
|
||||||
;
|
|
||||||
|
|
||||||
private final byte code;
|
|
||||||
|
|
||||||
TapAction(final byte code) {
|
|
||||||
this.code = code;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum TapFunction {
|
private byte[] encodeMessage(byte command1, byte command2, byte[] payload) {
|
||||||
VOLUMEDOWN(1),
|
int size = 8 + payload.length + 1;
|
||||||
VOLUMEUP(0),
|
ByteBuffer msgBuf = ByteBuffer.allocate(size);
|
||||||
NEXT( 3),
|
msgBuf.order(ByteOrder.BIG_ENDIAN);
|
||||||
PREVIOUS(2),
|
msgBuf.put(new byte[] {0x08, (byte) 0xee, 0x00, 0x00, 0x00}); // header
|
||||||
PLAYPAUSE(6),
|
msgBuf.put(command1);
|
||||||
VOICE_ASSISTANT(5),
|
msgBuf.put(command2);
|
||||||
AMBIENT_SOUND_CONTROL(4)
|
msgBuf.put((byte) size);
|
||||||
;
|
|
||||||
|
|
||||||
private final int code;
|
msgBuf.put(payload);
|
||||||
|
|
||||||
TapFunction(final int code) {
|
byte checksum = -10;
|
||||||
this.code = code;
|
checksum += command1 + command2 + size;
|
||||||
|
for (int b : payload) {
|
||||||
|
checksum += b;
|
||||||
}
|
}
|
||||||
}
|
msgBuf.put(checksum);
|
||||||
|
|
||||||
|
return msgBuf.array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
|
||||||
|
|
||||||
|
enum TapAction {
|
||||||
|
SINGLE_TAP((byte) 0x02),
|
||||||
|
DOUBLE_TAP((byte) 0x00),
|
||||||
|
TRIPLE_TAP((byte) 0x05),
|
||||||
|
LONG_PRESS((byte) 0x01)
|
||||||
|
;
|
||||||
|
|
||||||
|
private final byte code;
|
||||||
|
|
||||||
|
TapAction(final byte code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package nodomain.freeyourgadget.gadgetbridge.service.devices.soundcore;
|
||||||
|
enum TapFunction {
|
||||||
|
VOLUMEDOWN(1),
|
||||||
|
VOLUMEUP(0),
|
||||||
|
NEXT( 3),
|
||||||
|
PREVIOUS(2),
|
||||||
|
PLAYPAUSE(6),
|
||||||
|
VOICE_ASSISTANT(5),
|
||||||
|
AMBIENT_SOUND_CONTROL(4)
|
||||||
|
;
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
TapFunction(final int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user