Krolyxon
Commit 4c49f6c

Branches

Refs →

budctlcratesbudctl-coresrcdevicesmod.rs

103 lines · 4.0 KB · Rust

1//! Device plugins.
2//!
3//! To support a new pair of buds, add one module here and list it in [`REGISTRY`]. Transport,
4//! CLI and GUI code do not change.
5
6use crate::bluez::PairedDevice;
7use crate::bt::Uuid;
8use crate::error::{Error, Result};
9use crate::status::{BudFit, NoiseControl, NoiseMode, Status, Switch, TouchChange, TouchControls};
10use crate::transport::Transport;
11
12pub mod realme_t310;
13
14/// Every model budctl supports.
15pub static REGISTRY: &[&dyn Device] = &[&realme_t310::RealmeT310];
16
17/// One supported model.
18pub trait Device: Sync {
19 /// Model name, e.g. `realme Buds T310`.
20 fn name(&self) -> &'static str;
21
22 /// Whether a paired device is this model, judged from BlueZ data alone.
23 fn matches(&self, device: &PairedDevice) -> bool;
24
25 /// The control service(s), in the order to try. SDP turns each into an RFCOMM channel.
26 fn rfcomm_uuids(&self) -> &'static [Uuid];
27
28 /// Run the model's init sequence on a fresh link and return a ready session.
29 fn open(&self, link: Box<dyn Transport>) -> Result<Box<dyn Session>>;
30}
31
32/// An open control link to one pair of buds. Dropping it closes the link.
33pub trait Session: Send {
34 /// Battery, noise control, EQ, switches and whatever else the model can read.
35 fn status(&mut self) -> Result<Status>;
36
37 /// The touch-control (gesture) settings of each bud.
38 fn touch_controls(&mut self) -> Result<TouchControls> {
39 Err(Error::Unsupported(
40 "these buds have no touch-control settings budctl can read".to_owned(),
41 ))
42 }
43
44 /// Set the noise-control mode, then read it back. Returns the mode the buds now report.
45 fn set_noise_control(&mut self, _mode: NoiseMode) -> Result<NoiseControl> {
46 Err(Error::Unsupported(
47 "these buds have no noise-control setting budctl can change".to_owned(),
48 ))
49 }
50
51 /// Select a built-in EQ preset by name, then read it back. Returns the preset now in use.
52 fn set_eq(&mut self, _preset: &str) -> Result<String> {
53 Err(Error::Unsupported(
54 "budctl cannot change the EQ on these buds".to_owned(),
55 ))
56 }
57
58 /// Start (`true`) or stop ringing the buds so they can be found. Only the ack can be
59 /// checked: there is no state to read back.
60 fn find(&mut self, _ring: bool) -> Result<()> {
61 Err(Error::Unsupported("these buds cannot ring through budctl".to_owned()))
62 }
63
64 /// Turn an on/off setting ([`Switch::key`]) on or off, then read it back.
65 fn set_switch(&mut self, key: &str, _on: bool) -> Result<Switch> {
66 Err(Error::Unsupported(format!("budctl cannot change {key} on these buds")))
67 }
68
69 /// Run a fit test and wait for its result. Both buds must be in the ears.
70 fn fit_test(&mut self) -> Result<Vec<BudFit>> {
71 Err(Error::Unsupported(
72 "these buds have no fit test budctl can run".to_owned(),
73 ))
74 }
75
76 /// Stop a fit test that is still running.
77 fn stop_fit_test(&mut self) -> Result<()> {
78 Err(Error::Unsupported(
79 "these buds have no fit test budctl can run".to_owned(),
80 ))
81 }
82
83 /// Set the noise-control modes a hold steps through (`off`, `transparency`, `anc`), then
84 /// read it back. Returns the modes the buds now report.
85 fn set_hold_cycle(&mut self, _modes: &[&str]) -> Result<Vec<String>> {
86 Err(Error::Unsupported(
87 "budctl cannot change the hold cycle on these buds".to_owned(),
88 ))
89 }
90
91 /// Give a touch gesture a new action, on `side` (`left`, `right` or `both`), then read the
92 /// table back. With `dry_run`, read the table and work out the write, but send nothing.
93 fn set_touch(&mut self, _side: &str, _gesture: &str, _action: &str, _dry_run: bool) -> Result<TouchChange> {
94 Err(Error::Unsupported(
95 "budctl cannot change the touch controls on these buds".to_owned(),
96 ))
97 }
98}
99
100/// The supported model a paired device is, if any.
101pub fn identify(device: &PairedDevice) -> Option<&'static dyn Device> {
102 REGISTRY.iter().copied().find(|model| model.matches(device))
103}