Skip to content

Commit 5ea8d1d

Browse files
committed
linux-rust: add skeleton for other devices
1 parent c336836 commit 5ea8d1d

20 files changed

Lines changed: 1450 additions & 339 deletions

File tree

linux-rust/Cargo.lock

Lines changed: 65 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

linux-rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ uuid = "1.18.1"
1111
log = "0.4.28"
1212
dbus = "0.9.9"
1313
hex = "0.4.3"
14-
iced = {version = "0.13.1", features = ["tokio"]}
14+
iced = { version = "0.13.1", features = ["tokio", "image"] }
1515
libpulse-binding = "2.30.1"
1616
ksni = "0.3.1"
1717
image = "0.25.8"

linux-rust/assets/icon.png

266 KB
Loading

linux-rust/src/bluetooth/aacp.rs

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ use tokio::time::{sleep, Instant};
88
use std::collections::HashMap;
99
use serde::{Deserialize, Serialize};
1010
use serde_json;
11+
use crate::devices::airpods::AirPodsInformation;
12+
use crate::devices::enums::{DeviceData, DeviceInformation, DeviceType};
1113
use crate::utils::get_devices_path;
1214

1315
const PSM: u16 = 0x1001;
@@ -280,45 +282,11 @@ pub enum AACPEvent {
280282
}
281283

282284
#[derive(Debug, Clone, Serialize, Deserialize)]
283-
pub enum DeviceType {
284-
AirPods,
285-
}
286-
287-
#[derive(Debug, Clone, Serialize, Deserialize)]
288-
pub struct LEData {
285+
pub struct AirPodsLEKeys {
289286
pub irk: String,
290287
pub enc_key: String,
291288
}
292289

293-
#[derive(Debug, Clone, Serialize, Deserialize)]
294-
pub struct AirPodsInformation {
295-
pub name: String,
296-
pub model_number: String,
297-
pub manufacturer: String,
298-
pub serial_number: String,
299-
pub version1: String,
300-
pub version2: String,
301-
pub hardware_revision: String,
302-
pub updater_identifier: String,
303-
pub left_serial_number: String,
304-
pub right_serial_number: String,
305-
pub version3: String,
306-
}
307-
308-
#[derive(Debug, Clone, Serialize, Deserialize)]
309-
#[serde(tag = "kind", content = "data")]
310-
pub enum DeviceInformation {
311-
AirPods(AirPodsInformation),
312-
}
313-
314-
#[derive(Debug, Clone, Serialize, Deserialize)]
315-
pub struct DeviceData {
316-
pub name: String,
317-
pub type_: DeviceType,
318-
pub le: LEData,
319-
pub information: Option<DeviceInformation>,
320-
}
321-
322290
pub struct AACPManagerState {
323291
pub sender: Option<mpsc::Sender<Vec<u8>>>,
324292
pub control_command_status_list: Vec<ControlCommandStatus>,
@@ -647,7 +615,7 @@ impl AACPManager {
647615
strings.push(s.to_string());
648616
}
649617
}
650-
strings.remove(0); // Remove the first empty string as per comment
618+
strings.remove(0);
651619
let info = AirPodsInformation {
652620
name: strings.get(0).cloned().unwrap_or_default(),
653621
model_number: strings.get(1).cloned().unwrap_or_default(),
@@ -660,6 +628,10 @@ impl AACPManager {
660628
left_serial_number: strings.get(8).cloned().unwrap_or_default(),
661629
right_serial_number: strings.get(9).cloned().unwrap_or_default(),
662630
version3: strings.get(10).cloned().unwrap_or_default(),
631+
le_keys: AirPodsLEKeys {
632+
irk: "".to_string(),
633+
enc_key: "".to_string(),
634+
},
663635
};
664636
let mut state = self.state.lock().await;
665637
if let Some(mac) = state.airpods_mac {
@@ -715,12 +687,29 @@ impl AACPManager {
715687
let device_data = state.devices.entry(mac_str.clone()).or_insert(DeviceData {
716688
name: mac_str.clone(),
717689
type_: DeviceType::AirPods,
718-
le: LEData { irk: "".to_string(), enc_key: "".to_string() },
719690
information: None,
720691
});
721692
match kt {
722-
ProximityKeyType::Irk => device_data.le.irk = hex::encode(key_data),
723-
ProximityKeyType::EncKey => device_data.le.enc_key = hex::encode(key_data),
693+
ProximityKeyType::Irk => {
694+
match device_data.information.as_mut() {
695+
Some(DeviceInformation::AirPods(info)) => {
696+
info.le_keys.irk = hex::encode(key_data);
697+
}
698+
_ => {
699+
error!("Device information is not AirPods for adding LE IRK.");
700+
}
701+
}
702+
}
703+
ProximityKeyType::EncKey => {
704+
match device_data.information.as_mut() {
705+
Some(DeviceInformation::AirPods(info)) => {
706+
info.le_keys.enc_key = hex::encode(key_data);
707+
}
708+
_ => {
709+
error!("Device information is not AirPods for adding LE encryption key.");
710+
}
711+
}
712+
}
724713
}
725714
}
726715
}

linux-rust/src/bluetooth/att.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,62 +16,67 @@ const OPCODE_READ_REQUEST: u8 = 0x0A;
1616
const OPCODE_WRITE_REQUEST: u8 = 0x12;
1717
const OPCODE_HANDLE_VALUE_NTF: u8 = 0x1B;
1818
const OPCODE_WRITE_RESPONSE: u8 = 0x13;
19+
const RESPONSE_TIMEOUT: u64 = 5000;
1920

2021
#[repr(u16)]
2122
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
2223
pub enum ATTHandles {
23-
Transparency = 0x18,
24-
LoudSoundReduction = 0x1B,
25-
HearingAid = 0x2A,
24+
AirPodsTransparency = 0x18,
25+
AirPodsLoudSoundReduction = 0x1B,
26+
AirPodsHearingAid = 0x2A,
27+
NothingEverything = 0x8002,
28+
NothingEverythingRead = 0x8005 // for some reason, and not the same as the write handle
2629
}
2730

2831
#[repr(u16)]
2932
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3033
pub enum ATTCCCDHandles {
31-
Transparency = ATTHandles::Transparency as u16 + 1,
32-
LoudSoundReduction = ATTHandles::LoudSoundReduction as u16 + 1,
33-
HearingAid = ATTHandles::HearingAid as u16 + 1,
34+
Transparency = ATTHandles::AirPodsTransparency as u16 + 1,
35+
LoudSoundReduction = ATTHandles::AirPodsLoudSoundReduction as u16 + 1,
36+
HearingAid = ATTHandles::AirPodsHearingAid as u16 + 1,
3437
}
3538

3639
impl From<ATTHandles> for ATTCCCDHandles {
3740
fn from(handle: ATTHandles) -> Self {
3841
match handle {
39-
ATTHandles::Transparency => ATTCCCDHandles::Transparency,
40-
ATTHandles::LoudSoundReduction => ATTCCCDHandles::LoudSoundReduction,
41-
ATTHandles::HearingAid => ATTCCCDHandles::HearingAid,
42+
ATTHandles::AirPodsTransparency => ATTCCCDHandles::Transparency,
43+
ATTHandles::AirPodsLoudSoundReduction => ATTCCCDHandles::LoudSoundReduction,
44+
ATTHandles::AirPodsHearingAid => ATTCCCDHandles::HearingAid,
45+
ATTHandles::NothingEverything => panic!("No CCCD for NothingEverything handle"), // we don't request it
46+
ATTHandles::NothingEverythingRead => panic!("No CCD for NothingEverythingRead handle") // it sends notifications without CCCD
4247
}
4348
}
4449
}
4550

4651
struct ATTManagerState {
4752
sender: Option<mpsc::Sender<Vec<u8>>>,
4853
listeners: HashMap<u16, Vec<mpsc::UnboundedSender<Vec<u8>>>>,
49-
responses: mpsc::UnboundedReceiver<Vec<u8>>,
50-
response_tx: mpsc::UnboundedSender<Vec<u8>>,
5154
}
5255

5356
impl ATTManagerState {
5457
fn new() -> Self {
55-
let (tx, rx) = mpsc::unbounded_channel();
5658
ATTManagerState {
5759
sender: None,
58-
listeners: HashMap::new(),
59-
responses: rx,
60-
response_tx: tx,
60+
listeners: HashMap::new()
6161
}
6262
}
6363
}
6464

6565
#[derive(Clone)]
6666
pub struct ATTManager {
6767
state: Arc<Mutex<ATTManagerState>>,
68+
response_rx: Arc<Mutex<mpsc::UnboundedReceiver<Vec<u8>>>>,
69+
response_tx: mpsc::UnboundedSender<Vec<u8>>,
6870
tasks: Arc<Mutex<JoinSet<()>>>,
6971
}
7072

7173
impl ATTManager {
7274
pub fn new() -> Self {
75+
let (tx, rx) = mpsc::unbounded_channel();
7376
ATTManager {
7477
state: Arc::new(Mutex::new(ATTManagerState::new())),
78+
response_rx: Arc::new(Mutex::new(rx)),
79+
response_tx: tx,
7580
tasks: Arc::new(Mutex::new(JoinSet::new())),
7681
}
7782
}
@@ -184,11 +189,18 @@ impl ATTManager {
184189
}
185190

186191
async fn read_response(&self) -> Result<Vec<u8>> {
187-
let mut state = self.state.lock().await;
188-
match tokio::time::timeout(Duration::from_millis(2000), state.responses.recv()).await {
192+
debug!("Waiting for response...");
193+
let mut rx = self.response_rx.lock().await;
194+
match tokio::time::timeout(Duration::from_millis(RESPONSE_TIMEOUT), rx.recv()).await {
189195
Ok(Some(resp)) => Ok(resp),
190-
Ok(None) => Err(Error::from(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "Response channel closed"))),
191-
Err(_) => Err(Error::from(std::io::Error::new(std::io::ErrorKind::TimedOut, "Response timeout"))),
196+
Ok(None) => Err(Error::from(std::io::Error::new(
197+
std::io::ErrorKind::UnexpectedEof,
198+
"Response channel closed"
199+
))),
200+
Err(_) => Err(Error::from(std::io::Error::new(
201+
std::io::ErrorKind::TimedOut,
202+
"Response timeout"
203+
))),
192204
}
193205
}
194206
}
@@ -217,10 +229,11 @@ async fn recv_thread(manager: ATTManager, sp: Arc<SeqPacket>) {
217229
let _ = listener.send(value.clone());
218230
}
219231
}
232+
} else if data[0] == OPCODE_WRITE_RESPONSE {
233+
let _ = manager.response_tx.send(vec![]);
220234
} else {
221235
// Response
222-
let state = manager.state.lock().await;
223-
let _ = state.response_tx.send(data[1..].to_vec());
236+
let _ = manager.response_tx.send(data[1..].to_vec());
224237
}
225238
}
226239
Err(e) => {

0 commit comments

Comments
 (0)