Skip to content

Commit

Permalink
[Feature] Initial FreeBuds Studio driver impl (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
melianmiko committed Nov 17, 2024
1 parent 3e9d99b commit 175c85e
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ If your device isn't listed here, you could try to use it with profile for other
- [HUAWEI FreeBuds Pro 2](./docs/devices/HUAWEI_FreeBuds_Pro_2.md)
- [HUAWEI FreeBuds Pro 3](./docs/devices/HUAWEI_FreeBuds_Pro_3.md)
- [HUAWEI FreeBuds SE](./docs/devices/HUAWEI_FreeBuds_SE.md)
- [HUAWEI FreeBuds Studio](./docs/devices/HUAWEI_FreeBuds_Studio.md)
- [HUAWEI FreeLace Pro](./docs/devices/HUAWEI_FreeLace_Pro.md)
- [HUAWEI FreeLace Pro 2](./docs/devices/HUAWEI_FreeLace_Pro_2.md)

Expand Down
19 changes: 19 additions & 0 deletions docs/devices/HUAWEI_FreeBuds_Studio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# HUAWEI FreeBuds Studio

Protocol: Huawei SPP, port 1

## Features

- Fetch device information and battery level: ❓ (untested)
- Control noise cancellation: ❓ (untested)
- With cancellation level
- With dynamic cancellation
- Wear detection (aka auto-pause) configuration: ❓ (untested)
- Equalizer: ❓ (untested)
- 3 built-in presets, hardcoded
- AI Life didn't see current equalizer mode, looks like application or firmware bug
- Change voice language: ❓ (no information, currently disabled)

## Not planned features

- Firmware update
Binary file modified docs/research.ods
Binary file not shown.
12 changes: 7 additions & 5 deletions openfreebuds/driver/constants.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from openfreebuds.driver.generic_debug import *
from openfreebuds.driver.huawei import *
from openfreebuds.driver.huawei.driver.per_model.buds_studio import OfbDriverHuaweiStudio

DEVICE_TO_DRIVER_MAP = {
"HONOR Earbuds 2": OfbDriverHuawei4I,
"HUAWEI FreeBuds 4i": OfbDriverHuawei4I,
"HUAWEI FreeBuds 5i": OfbDriverHuawei5I,
"HUAWEI FreeBuds 6i": OfbDriverHuawei6I,
"HUAWEI FreeBuds SE": OfbDriverHuaweiSe,
"HUAWEI FreeLace Pro": OfbDriverHuaweiLacePro,
"HUAWEI FreeLace Pro 2": OfbDriverHuaweiLacePro2,
"HUAWEI FreeBuds 4i": OfbDriverHuawei4I,
"HONOR Earbuds 2": OfbDriverHuawei4I,
"HUAWEI FreeBuds Pro": OfbDriverHuaweiPro,
"HUAWEI FreeBuds Pro 2": OfbDriverHuaweiPro2,
"HUAWEI FreeBuds Pro 3": OfbDriverHuaweiPro3,
"HUAWEI FreeBuds SE": OfbDriverHuaweiSe,
"HUAWEI FreeBuds Studio": OfbDriverHuaweiStudio,
"HUAWEI FreeLace Pro": OfbDriverHuaweiLacePro,
"HUAWEI FreeLace Pro 2": OfbDriverHuaweiLacePro2,
"Debug: Virtual device": OfbFileDeviceDriver,
}
19 changes: 19 additions & 0 deletions openfreebuds/driver/huawei/driver/per_model/buds_studio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from openfreebuds.driver.huawei.driver.generic import OfbDriverHuaweiGeneric
from openfreebuds.driver.huawei.handler import *


class OfbDriverHuaweiStudio(OfbDriverHuaweiGeneric):
def __init__(self, address):
super().__init__(address)
self._spp_service_port = 1
self.handlers = [
OfbHuaweiInfoHandler(),
OfbHuaweiBatteryHandler(w_tws=False),
OfbHuaweiAncHandler(w_cancel_lvl=True, w_cancel_dynamic=True, w_voice_boost=True),
OfbHuaweiConfigAutoPauseHandler(),
OfbHuaweiEqualizerPresetHandler(wo_read=True, w_presets={
1: "default",
2: "hardbass",
3: "treble",
}),
]
25 changes: 24 additions & 1 deletion openfreebuds/driver/huawei/handler/config_equalizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,22 @@ def __init__(
w_presets: Optional[dict[int, str]] = None,
w_custom: bool = False,
w_fake_built_in: bool = False,
wo_read: bool = False,
w_custom_rows: int = 10,
w_custom_max_count: int = 3,
):
"""
Equalizer configuration handler
@param w_presets: Available built-in presets
@param w_custom: Allow custom modes flag
@param w_fake_built_in: Allow fake built-in modes flag
@param wo_read: Disallow read request flag (for legacy devices)
@param w_custom_rows: Count of equalizer rows, for custom modes
@param w_custom_max_count: Max count of custom modes available in device
"""
self.w_custom: bool = w_custom
self.wo_read: bool = wo_read
self.w_custom_rows = w_custom_rows
self.w_custom_max_count = w_custom_max_count
self.w_fake_built_in = w_fake_built_in
Expand All @@ -71,6 +83,13 @@ def __init__(
self.preset_data = self.default_preset_data

async def on_init(self):
if self.wo_read:
await self.driver.put_property("sound", None, {
"equalizer_preset": "",
"equalizer_preset_options": ",".join([l for _, l, _ in self.preset_data])
}, extend_group=True)
return

resp = await self.driver.send_package(
HuaweiSppPackage.read_rq(b"\x2b\x4a", [1, 2, 3, 4, 5, 6, 7, 8])
)
Expand Down Expand Up @@ -206,7 +225,11 @@ async def _set_current_mode(self, mode_str):
self.changes_saved = True

await self.driver.send_package(pkg)
await self.on_init()

if self.wo_read:
await self.driver.put_property("sound", "equalizer_preset", mode_str)
else:
await self.on_init()

async def on_package(self, package: HuaweiSppPackage):
new_props = {
Expand Down

0 comments on commit 175c85e

Please sign in to comment.