diff options
author | 2025-03-04 19:27:07 +0000 | |
---|---|---|
committer | 2025-03-04 20:18:27 +0000 | |
commit | cdca17e4110424465274d2e34c9fa49f56776c42 (patch) | |
tree | 076e42b27c6fc3785497d5c814d851ba5a0a0327 /offload | |
parent | 10cf7ae5abf5a0d60a703210b1c0b4af52d9916a (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.aidl | 7 | ||||
-rw-r--r-- | offload/leaudio/hci/arbiter.rs | 4 | ||||
-rw-r--r-- | offload/leaudio/hci/proxy.rs | 77 | ||||
-rw-r--r-- | offload/leaudio/hci/service.rs | 10 | ||||
-rw-r--r-- | offload/leaudio/hci/tests.rs | 42 |
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(), ); |