summaryrefslogtreecommitdiff
path: root/offload
diff options
context:
space:
mode:
author Antoine SOULIER <asoulier@google.com> 2025-03-04 19:27:07 +0000
committer Antoine SOULIER <asoulier@google.com> 2025-03-04 20:18:27 +0000
commitcdca17e4110424465274d2e34c9fa49f56776c42 (patch)
tree076e42b27c6fc3785497d5c814d851ba5a0a0327 /offload
parent10cf7ae5abf5a0d60a703210b1c0b4af52d9916a (diff)
LE-Audio Software Offload: Allow ISOAL fragmentation in PDU's
Bug: 375486605 Flag: EXEMPT, enabled by vendor Test: atest libbluetooth_offload_leaudio_hci_test Change-Id: I8813e852d06312e1a048f6f589feeb1e42818650
Diffstat (limited to 'offload')
-rw-r--r--offload/leaudio/aidl/android/hardware/bluetooth/offload/leaudio/StreamConfiguration.aidl7
-rw-r--r--offload/leaudio/hci/arbiter.rs4
-rw-r--r--offload/leaudio/hci/proxy.rs77
-rw-r--r--offload/leaudio/hci/service.rs10
-rw-r--r--offload/leaudio/hci/tests.rs42
5 files changed, 93 insertions, 47 deletions
diff --git a/offload/leaudio/aidl/android/hardware/bluetooth/offload/leaudio/StreamConfiguration.aidl b/offload/leaudio/aidl/android/hardware/bluetooth/offload/leaudio/StreamConfiguration.aidl
index 944facb2ef..6910978e3b 100644
--- a/offload/leaudio/aidl/android/hardware/bluetooth/offload/leaudio/StreamConfiguration.aidl
+++ b/offload/leaudio/aidl/android/hardware/bluetooth/offload/leaudio/StreamConfiguration.aidl
@@ -37,12 +37,7 @@ parcelable StreamConfiguration {
int maxSduSize;
/**
- * Number of PDU's transmitted by ISO-Intervals
- */
- int burstNumber;
-
- /**
- * How many consecutive Isochronous Intervals can be used to transmit a PDU
+ * How many consecutive Isochronous Intervals can be used to transmit an SDU
*/
int flushTimeout;
}
diff --git a/offload/leaudio/hci/arbiter.rs b/offload/leaudio/hci/arbiter.rs
index 072295f568..71b3ffbaee 100644
--- a/offload/leaudio/hci/arbiter.rs
+++ b/offload/leaudio/hci/arbiter.rs
@@ -53,6 +53,10 @@ impl Arbiter {
Self { state_cvar, thread: Some(thread), max_buf_len }
}
+ pub fn max_buf_len(&self) -> usize {
+ self.max_buf_len
+ }
+
pub fn add_connection(&self, handle: u16) {
let (state, _) = &*self.state_cvar;
if state.lock().unwrap().in_transit.insert(handle, 0).is_some() {
diff --git a/offload/leaudio/hci/proxy.rs b/offload/leaudio/hci/proxy.rs
index 604bde356d..986da0b88e 100644
--- a/offload/leaudio/hci/proxy.rs
+++ b/offload/leaudio/hci/proxy.rs
@@ -39,14 +39,21 @@ struct State {
}
struct BigParameters {
- bis_handles: Vec<u16>,
sdu_interval: u32,
+ max_sdu_size: u16,
+ bis_handles: Vec<u16>,
}
struct CigParameters {
- cis_handles: Vec<u16>,
sdu_interval_c_to_p: u32,
sdu_interval_p_to_c: u32,
+ cis: Vec<CisParameters>,
+}
+
+struct CisParameters {
+ handle: u16,
+ max_sdu_size_c_to_p: u16,
+ max_sdu_size_p_to_c: u16,
}
#[derive(Debug, Clone)]
@@ -73,30 +80,22 @@ enum IsoType {
struct IsoInDirection {
sdu_interval_us: u32,
max_sdu_size: u16,
- burst_number: u8,
flush_timeout: u8,
}
impl Stream {
fn new_cis(cig: &CigParameters, e: &hci::LeCisEstablished) -> Self {
+ let cis = cig.cis.iter().find(|&s| s.handle == e.connection_handle).unwrap();
let iso_interval_us = (e.iso_interval as u32) * 1250;
- if cig.sdu_interval_c_to_p != 0 {
- assert_eq!(iso_interval_us % cig.sdu_interval_c_to_p, 0, "Framing mode not supported");
- assert_eq!(
- iso_interval_us / cig.sdu_interval_c_to_p,
- e.bn_c_to_p.into(),
- "SDU fragmentation not supported"
- );
- }
- if cig.sdu_interval_p_to_c != 0 {
- assert_eq!(iso_interval_us % cig.sdu_interval_p_to_c, 0, "Framing mode not supported");
- assert_eq!(
- iso_interval_us / cig.sdu_interval_p_to_c,
- e.bn_p_to_c.into(),
- "SDU fragmentation not supported"
- );
- }
+ assert!(
+ cig.sdu_interval_c_to_p == 0 || (iso_interval_us % cig.sdu_interval_c_to_p) == 0,
+ "Framing mode not supported"
+ );
+ assert!(
+ cig.sdu_interval_p_to_c == 0 || (iso_interval_us % cig.sdu_interval_p_to_c) == 0,
+ "Framing mode not supported"
+ );
Self {
state: StreamState::Disabled,
@@ -104,14 +103,12 @@ impl Stream {
iso_type: IsoType::Cis {
c_to_p: IsoInDirection {
sdu_interval_us: cig.sdu_interval_c_to_p,
- max_sdu_size: e.max_pdu_c_to_p,
- burst_number: e.bn_c_to_p,
+ max_sdu_size: cis.max_sdu_size_c_to_p,
flush_timeout: e.ft_c_to_p,
},
_p_to_c: IsoInDirection {
sdu_interval_us: cig.sdu_interval_p_to_c,
- max_sdu_size: e.max_pdu_p_to_c,
- burst_number: e.bn_p_to_c,
+ max_sdu_size: cis.max_sdu_size_p_to_c,
flush_timeout: e.ft_p_to_c,
},
},
@@ -120,13 +117,7 @@ impl Stream {
fn new_bis(big: &BigParameters, e: &hci::LeCreateBigComplete) -> Self {
let iso_interval_us = (e.iso_interval as u32) * 1250;
-
assert_eq!(iso_interval_us % big.sdu_interval, 0, "Framing mode not supported");
- assert_eq!(
- iso_interval_us / big.sdu_interval,
- e.bn.into(),
- "SDU fragmentation not supported"
- );
Self {
state: StreamState::Disabled,
@@ -134,8 +125,7 @@ impl Stream {
iso_type: IsoType::Bis {
c_to_p: IsoInDirection {
sdu_interval_us: big.sdu_interval,
- max_sdu_size: e.max_pdu,
- burst_number: e.bn,
+ max_sdu_size: big.max_sdu_size,
flush_timeout: e.irc,
},
},
@@ -175,9 +165,17 @@ impl Module for LeAudioModule {
state.cig.insert(
c.cig_id,
CigParameters {
- cis_handles: vec![],
sdu_interval_c_to_p: c.sdu_interval_c_to_p,
sdu_interval_p_to_c: c.sdu_interval_p_to_c,
+ cis: c
+ .cis
+ .iter()
+ .map(|c| CisParameters {
+ handle: 0,
+ max_sdu_size_c_to_p: c.max_sdu_c_to_p,
+ max_sdu_size_p_to_c: c.max_sdu_p_to_c,
+ })
+ .collect(),
},
);
}
@@ -186,7 +184,11 @@ impl Module for LeAudioModule {
let mut state = self.state.lock().unwrap();
state.big.insert(
c.big_handle,
- BigParameters { bis_handles: vec![], sdu_interval: c.sdu_interval },
+ BigParameters {
+ sdu_interval: c.sdu_interval,
+ max_sdu_size: c.max_sdu,
+ bis_handles: vec![],
+ },
);
}
@@ -224,7 +226,11 @@ impl Module for LeAudioModule {
ReturnParameters::LeSetCigParameters(ref ret) if ret.status == Status::Success => {
let mut state = self.state.lock().unwrap();
let cig = state.cig.get_mut(&ret.cig_id).unwrap();
- cig.cis_handles = ret.connection_handles.clone();
+
+ assert!(cig.cis.len() == ret.connection_handles.len());
+ for (cis, &handle) in cig.cis.iter_mut().zip(ret.connection_handles.iter()) {
+ cis.handle = handle;
+ }
}
ReturnParameters::LeRemoveCig(ref ret) if ret.status == Status::Success => {
@@ -257,7 +263,6 @@ impl Module for LeAudioModule {
isoIntervalUs: stream.iso_interval_us as i32,
sduIntervalUs: c_to_p.sdu_interval_us as i32,
maxSduSize: c_to_p.max_sdu_size as i32,
- burstNumber: c_to_p.burst_number as i32,
flushTimeout: c_to_p.flush_timeout as i32,
},
);
@@ -279,7 +284,7 @@ impl Module for LeAudioModule {
let mut state = self.state.lock().unwrap();
let mut cig_values = state.cig.values();
let Some(cig) =
- cig_values.find(|&g| g.cis_handles.iter().any(|&h| h == e.connection_handle))
+ cig_values.find(|&g| g.cis.iter().any(|s| s.handle == e.connection_handle))
else {
panic!("CIG not set-up for CIS 0x{:03x}", e.connection_handle);
};
diff --git a/offload/leaudio/hci/service.rs b/offload/leaudio/hci/service.rs
index 05bc377287..98d77320cc 100644
--- a/offload/leaudio/hci/service.rs
+++ b/offload/leaudio/hci/service.rs
@@ -15,10 +15,10 @@
use android_hardware_bluetooth_offload_leaudio::{aidl, binder};
use crate::arbiter::Arbiter;
-use aidl::android::hardware::bluetooth::offload::leaudio::{
- IHciProxy::{BnHciProxy, BpHciProxy, IHciProxy},
- IHciProxyCallbacks::IHciProxyCallbacks,
+use aidl::android::hardware::bluetooth::offload::leaudio::IHciProxy::{
+ BnHciProxy, BpHciProxy, IHciProxy,
};
+use aidl::android::hardware::bluetooth::offload::leaudio::IHciProxyCallbacks::IHciProxyCallbacks;
use binder::{BinderFeatures, ExceptionCode, Interface, Result as BinderResult, Strong};
use bluetooth_offload_hci::IsoData;
use std::collections::HashMap;
@@ -104,6 +104,10 @@ impl IHciProxy for HciProxy {
let state = self.state.lock().unwrap();
if let Some(arbiter) = state.arbiter.upgrade() {
+ assert!(
+ data.len() <= arbiter.max_buf_len(),
+ "SDU Fragmentation over HCI is not supported"
+ );
arbiter.push_audio(&IsoData::new(handle, seqnum, data));
} else {
log::warn!("Trashing packet received in bad state");
diff --git a/offload/leaudio/hci/tests.rs b/offload/leaudio/hci/tests.rs
index dd55a93c2c..5d67b8ca13 100644
--- a/offload/leaudio/hci/tests.rs
+++ b/offload/leaudio/hci/tests.rs
@@ -101,7 +101,26 @@ fn cig() {
framing: 0,
max_transport_latency_c_to_p: 0,
max_transport_latency_p_to_c: 0,
- cis: vec![],
+ cis: vec![
+ hci::LeCisInCigParameters {
+ cis_id: 0,
+ max_sdu_c_to_p: 120,
+ max_sdu_p_to_c: 120,
+ phy_c_to_p: 0,
+ phy_p_to_c: 0,
+ rtn_c_to_p: 0,
+ rtn_p_to_c: 0,
+ },
+ hci::LeCisInCigParameters {
+ cis_id: 1,
+ max_sdu_c_to_p: 150,
+ max_sdu_p_to_c: 150,
+ phy_c_to_p: 0,
+ phy_p_to_c: 0,
+ rtn_c_to_p: 0,
+ rtn_p_to_c: 0,
+ },
+ ],
}
.to_bytes(),
);
@@ -491,7 +510,26 @@ fn merge() {
framing: 0,
max_transport_latency_c_to_p: 0,
max_transport_latency_p_to_c: 0,
- cis: vec![],
+ cis: vec![
+ hci::LeCisInCigParameters {
+ cis_id: 0,
+ max_sdu_c_to_p: 120,
+ max_sdu_p_to_c: 120,
+ phy_c_to_p: 0,
+ phy_p_to_c: 0,
+ rtn_c_to_p: 0,
+ rtn_p_to_c: 0,
+ },
+ hci::LeCisInCigParameters {
+ cis_id: 1,
+ max_sdu_c_to_p: 150,
+ max_sdu_p_to_c: 150,
+ phy_c_to_p: 0,
+ phy_p_to_c: 0,
+ rtn_c_to_p: 0,
+ rtn_p_to_c: 0,
+ },
+ ],
}
.to_bytes(),
);