Redmi Buds: Switch to BTBR support class, add headphones features

This commit is contained in:
José Rebelo
2026-01-01 16:32:20 +00:00
parent 158c59ce7b
commit 81f0c7fa75
8 changed files with 38 additions and 90 deletions
@@ -19,6 +19,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices.redmibuds;
import androidx.annotation.NonNull;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractBLClassicDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.BatteryConfig;
@@ -55,6 +56,13 @@ public abstract class AbstractRedmiBudsCoordinator extends AbstractBLClassicDevi
return new BatteryConfig[]{battery1, battery2, battery3};
}
@Override
public DeviceSpecificSettings getDeviceSpecificSettings(final GBDevice device) {
final DeviceSpecificSettings deviceSpecificSettings = new DeviceSpecificSettings();
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_headphones);
return deviceSpecificSettings;
}
@Override
public int getDefaultIconResource() {
return R.drawable.ic_device_nothingear;
@@ -7,6 +7,7 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.DeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.devices.redmibuds.RedmiBuds3ProDeviceSupport;
@@ -34,6 +35,10 @@ public class RedmiBuds3ProCoordinator extends AbstractRedmiBudsCoordinator {
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds3pro_headphones);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds3pro_sound);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds3pro_gestures);
deviceSpecificSettings.addSubScreen(
DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS,
R.xml.devicesettings_headphones
);
return deviceSpecificSettings;
}
@@ -21,6 +21,7 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class RedmiBuds5ProCoordinator extends AbstractRedmiBudsCoordinator {
@@ -40,6 +41,10 @@ public class RedmiBuds5ProCoordinator extends AbstractRedmiBudsCoordinator {
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_headphones);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_gestures);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_sound);
deviceSpecificSettings.addSubScreen(
DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS,
R.xml.devicesettings_headphones
);
return deviceSpecificSettings;
}
@@ -21,6 +21,7 @@ import java.util.regex.Pattern;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettings;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsCustomizer;
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSpecificSettingsScreen;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class RedmiBuds6ProCoordinator extends AbstractRedmiBudsCoordinator {
@@ -40,6 +41,10 @@ public class RedmiBuds6ProCoordinator extends AbstractRedmiBudsCoordinator {
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_headphones);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_gestures);
deviceSpecificSettings.addRootScreen(R.xml.devicesettings_redmibuds5pro_sound);
deviceSpecificSettings.addSubScreen(
DeviceSpecificSettingsScreen.CALLS_AND_NOTIFICATIONS,
R.xml.devicesettings_headphones
);
return deviceSpecificSettings;
}
@@ -1,18 +1,10 @@
package nodomain.freeyourgadget.gadgetbridge.service.devices.redmibuds;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
public class RedmiBuds3ProDeviceSupport extends RedmiBudsDeviceSupport {
@Override
protected GBDeviceProtocol createDeviceProtocol() {
protected RedmiBuds3ProProtocol createDeviceProtocol() {
return new RedmiBuds3ProProtocol(getDevice());
}
@Override
protected GBDeviceIoThread createDeviceIOThread() {
return new RedmiBudsIOThread(getDevice(), getContext(),
(RedmiBuds3ProProtocol) getDeviceProtocol(),
RedmiBuds3ProDeviceSupport.this, getBluetoothAdapter());
}
}
@@ -16,25 +16,24 @@
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.redmibuds;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractSerialDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceIoThread;
import nodomain.freeyourgadget.gadgetbridge.service.serial.GBDeviceProtocol;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.serial.AbstractHeadphoneSerialDeviceSupportV2;
public class RedmiBudsDeviceSupport extends AbstractHeadphoneSerialDeviceSupportV2<RedmiBudsProtocol> {
public RedmiBudsDeviceSupport() {
addSupportedService(RedmiBudsProtocol.UUID_DEVICE_CTRL);
}
public class RedmiBudsDeviceSupport extends AbstractSerialDeviceSupport {
@Override
protected GBDeviceProtocol createDeviceProtocol() {
protected RedmiBudsProtocol createDeviceProtocol() {
return new RedmiBudsProtocol(getDevice());
}
@Override
protected GBDeviceIoThread createDeviceIOThread() {
return new RedmiBudsIOThread(getDevice(), getContext(),
(RedmiBudsProtocol) getDeviceProtocol(),
RedmiBudsDeviceSupport.this, getBluetoothAdapter());
}
@Override
public boolean useAutoConnect() {
return false;
protected TransactionBuilder initializeDevice(final TransactionBuilder builder) {
builder.write(mDeviceProtocol.encodeStartAuthentication());
builder.setDeviceState(GBDevice.State.INITIALIZING);
return builder;
}
}
@@ -1,66 +0,0 @@
/* Copyright (C) 2024 Jonathan Gobbo
This file is part of Gadgetbridge.
Gadgetbridge is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Gadgetbridge is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
package nodomain.freeyourgadget.gadgetbridge.service.devices.redmibuds;
import static nodomain.freeyourgadget.gadgetbridge.util.GB.hexdump;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.ParcelUuid;
import androidx.annotation.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.service.btclassic.BtClassicIoThread;
public class RedmiBudsIOThread extends BtClassicIoThread {
private static final Logger LOG = LoggerFactory.getLogger(RedmiBudsIOThread.class);
private final RedmiBudsProtocol redmiProtocol;
public RedmiBudsIOThread(GBDevice gbDevice, Context context, RedmiBudsProtocol redmiProtocol, RedmiBudsDeviceSupport deviceSupport, BluetoothAdapter btAdapter) {
super(gbDevice, context, redmiProtocol, deviceSupport, btAdapter);
this.redmiProtocol = redmiProtocol;
}
@Override
protected byte[] parseIncoming(InputStream stream) throws IOException {
byte[] buffer = new byte[1048576];
int bytes = stream.read(buffer);
LOG.debug("read {} bytes. {}", bytes, hexdump(buffer, 0, bytes));
return Arrays.copyOf(buffer, bytes);
}
@NonNull
@Override
protected UUID getUuidToConnect(@NonNull ParcelUuid[] uuids) {
return this.redmiProtocol.UUID_DEVICE_CTRL;
}
@Override
protected void initialize() {
write(redmiProtocol.encodeStartAuthentication());
setUpdateState(GBDevice.State.INITIALIZING);
}
}
@@ -54,7 +54,7 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class RedmiBudsProtocol extends GBDeviceProtocol {
private static final Logger LOG = LoggerFactory.getLogger(RedmiBudsProtocol.class);
final UUID UUID_DEVICE_CTRL = UUID.fromString("0000fd2d-0000-1000-8000-00805f9b34fb");
public static final UUID UUID_DEVICE_CTRL = UUID.fromString("0000fd2d-0000-1000-8000-00805f9b34fb");
private byte sequenceNumber = 0;