Skip to main content

bt_bass/
types.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use bt_bap::types::BroadcastId;
6use bt_common::core::ltv::LtValue;
7use bt_common::core::{AddressType, AdvertisingSetId, PeriodicAdvertisingInterval};
8use bt_common::generic_audio::metadata_ltv::*;
9use bt_common::packet_encoding::{Decodable, Encodable, Error as PacketError};
10use bt_common::{decodable_enum, Uuid};
11use std::str::FromStr;
12
13pub const ADDRESS_BYTE_SIZE: usize = 6;
14const NUM_SUBGROUPS_BYTE_SIZE: usize = 1;
15const PA_SYNC_BYTE_SIZE: usize = 1;
16const SOURCE_ID_BYTE_SIZE: usize = 1;
17
18/// 16-bit UUID values for the Broadcast Audio Scan Service and its
19/// characteristics.
20pub const BROADCAST_AUDIO_SCAN_SERVICE_UUID: Uuid = Uuid::from_u16(0x184F);
21pub const BROADCAST_AUDIO_SCAN_CONTROL_POINT_UUID: Uuid = Uuid::from_u16(0x2BC7);
22pub const BROADCAST_RECEIVE_STATE_UUID: Uuid = Uuid::from_u16(0x2BC8);
23
24pub type SourceId = u8;
25
26/// Index into the vector of BIG subgroups. Valid value range is [0 to len of
27/// BIG vector).
28pub type SubgroupIndex = u8;
29
30/// BIS index value of a particular BIS. Valid value range is [1 to len of BIS]
31pub type BisIndex = u8;
32
33decodable_enum! {
34    pub enum ControlPointOpcode<u8, bt_common::packet_encoding::Error, OutOfRange> {
35        RemoteScanStopped = 0x00,
36        RemoteScanStarted = 0x01,
37        AddSource = 0x02,
38        ModifySource = 0x03,
39        SetBroadcastCode = 0x04,
40        RemoveSource = 0x05,
41    }
42}
43
44/// Broadcast Audio Scan Control Point characteristic opcode as defined in
45/// Broadcast Audio Scan Service spec v1.0 Section 3.1.
46impl ControlPointOpcode {
47    const BYTE_SIZE: usize = 1;
48}
49
50/// Trait for objects that represent a Broadcast Audio Scan Control Point
51/// characteristic. When written by a client, the Broadcast Audio Scan Control
52/// Point characteristic is defined as an 8-bit enumerated value, known as the
53/// opcode, followed by zero or more parameter octets. The opcode represents the
54/// operation that would be performed in the Broadcast Audio Scan Service
55/// server. See BASS spec v1.0 Section 3.1 for details.
56pub trait ControlPointOperation: Encodable<Error = PacketError> {
57    // Returns the expected opcode for this operation.
58    fn opcode() -> ControlPointOpcode;
59
60    // Given the raw encoded value of the opcode, verifies it and returns the
61    // equivalent ControlPointOpcode object.
62    fn check_opcode(raw_value: u8) -> Result<ControlPointOpcode, PacketError> {
63        let expected = Self::opcode();
64        let got = ControlPointOpcode::try_from(raw_value)?;
65        if got != expected {
66            return Err(PacketError::InvalidParameter(format!(
67                "got opcode {got:?}, expected {expected:?}"
68            )));
69        }
70        Ok(got)
71    }
72}
73
74/// See BASS spec v1.0 Section 3.1.1.2 for details.
75#[derive(Debug, PartialEq)]
76pub struct RemoteScanStoppedOperation;
77
78impl ControlPointOperation for RemoteScanStoppedOperation {
79    fn opcode() -> ControlPointOpcode {
80        ControlPointOpcode::RemoteScanStopped
81    }
82}
83
84impl Decodable for RemoteScanStoppedOperation {
85    type Error = PacketError;
86
87    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
88        const BYTE_SIZE: usize = ControlPointOpcode::BYTE_SIZE;
89        if buf.len() < BYTE_SIZE {
90            return (Err(PacketError::UnexpectedDataLength), buf.len());
91        }
92        (Self::check_opcode(buf[0]).map(|_| RemoteScanStoppedOperation), BYTE_SIZE)
93    }
94}
95
96impl Encodable for RemoteScanStoppedOperation {
97    type Error = PacketError;
98
99    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
100        if buf.len() < self.encoded_len() {
101            return Err(PacketError::BufferTooSmall);
102        }
103        buf[0] = Self::opcode() as u8;
104        Ok(())
105    }
106
107    fn encoded_len(&self) -> core::primitive::usize {
108        ControlPointOpcode::BYTE_SIZE
109    }
110}
111
112/// See BASS spec v1.0 Section 3.1.1.3 for details.
113#[derive(Debug, PartialEq)]
114pub struct RemoteScanStartedOperation;
115
116impl ControlPointOperation for RemoteScanStartedOperation {
117    fn opcode() -> ControlPointOpcode {
118        ControlPointOpcode::RemoteScanStarted
119    }
120}
121
122impl Decodable for RemoteScanStartedOperation {
123    type Error = PacketError;
124
125    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
126        const BYTE_SIZE: usize = ControlPointOpcode::BYTE_SIZE;
127        if buf.len() < BYTE_SIZE {
128            return (Err(PacketError::UnexpectedDataLength), buf.len());
129        }
130        (Self::check_opcode(buf[0]).map(|_| RemoteScanStartedOperation), BYTE_SIZE)
131    }
132}
133
134impl Encodable for RemoteScanStartedOperation {
135    type Error = PacketError;
136
137    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
138        if buf.len() < self.encoded_len() {
139            return Err(PacketError::BufferTooSmall);
140        }
141        buf[0] = Self::opcode() as u8;
142        Ok(())
143    }
144
145    fn encoded_len(&self) -> core::primitive::usize {
146        ControlPointOpcode::BYTE_SIZE
147    }
148}
149
150/// See BASS spec v1.0 Section 3.1.1.4 for details.
151#[derive(Debug, PartialEq)]
152pub struct AddSourceOperation {
153    pub(crate) advertiser_address_type: AddressType,
154    // Address in little endian.
155    pub(crate) advertiser_address: [u8; ADDRESS_BYTE_SIZE],
156    pub(crate) advertising_sid: AdvertisingSetId,
157    pub(crate) broadcast_id: BroadcastId,
158    pub(crate) pa_sync: PaSync,
159    pub(crate) pa_interval: PeriodicAdvertisingInterval,
160    pub(crate) subgroups: Vec<BigSubgroup>,
161}
162
163impl AddSourceOperation {
164    const MIN_PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE
165        + AddressType::BYTE_SIZE
166        + ADDRESS_BYTE_SIZE
167        + AdvertisingSetId::BYTE_SIZE
168        + BroadcastId::BYTE_SIZE
169        + PA_SYNC_BYTE_SIZE
170        + PeriodicAdvertisingInterval::BYTE_SIZE
171        + NUM_SUBGROUPS_BYTE_SIZE;
172
173    pub fn new(
174        address_type: AddressType,
175        advertiser_address: [u8; ADDRESS_BYTE_SIZE],
176        advertising_sid: AdvertisingSetId,
177        broadcast_id: BroadcastId,
178        pa_sync: PaSync,
179        pa_interval: PeriodicAdvertisingInterval,
180        subgroups: Vec<BigSubgroup>,
181    ) -> Self {
182        AddSourceOperation {
183            advertiser_address_type: address_type,
184            advertiser_address,
185            advertising_sid,
186            broadcast_id: broadcast_id,
187            pa_sync,
188            pa_interval,
189            subgroups,
190        }
191    }
192}
193
194impl ControlPointOperation for AddSourceOperation {
195    fn opcode() -> ControlPointOpcode {
196        ControlPointOpcode::AddSource
197    }
198}
199
200impl Decodable for AddSourceOperation {
201    type Error = PacketError;
202
203    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
204        if buf.len() < Self::MIN_PACKET_SIZE {
205            return (Err(PacketError::UnexpectedDataLength), buf.len());
206        }
207
208        let decode_fn = || {
209            let _ = Self::check_opcode(buf[0])?;
210            let advertiser_address_type = AddressType::try_from(buf[1])?;
211            let mut advertiser_address = [0; ADDRESS_BYTE_SIZE];
212            advertiser_address.clone_from_slice(&buf[2..8]);
213            let advertising_sid = AdvertisingSetId::try_from(buf[8])?;
214            let broadcast_id = BroadcastId::decode(&buf[9..12]).0?;
215            let pa_sync = PaSync::try_from(buf[12])?;
216            let pa_interval =
217                PeriodicAdvertisingInterval(u16::from_le_bytes(buf[13..15].try_into().unwrap()));
218            let num_subgroups = buf[15] as usize;
219            let mut subgroups = Vec::new();
220
221            let mut idx: usize = 16;
222            for _i in 0..num_subgroups {
223                if buf.len() <= idx {
224                    return Err(PacketError::UnexpectedDataLength);
225                }
226                let (decoded, consumed) = BigSubgroup::decode(&buf[idx..]);
227                subgroups.push(decoded?);
228                idx += consumed;
229            }
230            Ok((
231                Self {
232                    advertiser_address_type,
233                    advertiser_address,
234                    advertising_sid,
235                    broadcast_id,
236                    pa_sync,
237                    pa_interval,
238                    subgroups,
239                },
240                idx,
241            ))
242        };
243
244        match decode_fn() {
245            Ok((result, consumed)) => (Ok(result), consumed),
246            Err(e) => (Err(e), buf.len()),
247        }
248    }
249}
250
251impl Encodable for AddSourceOperation {
252    type Error = PacketError;
253
254    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
255        if buf.len() < self.encoded_len() {
256            return Err(PacketError::BufferTooSmall);
257        }
258
259        buf[0] = Self::opcode() as u8;
260        buf[1] = self.advertiser_address_type as u8;
261        buf[2..8].copy_from_slice(&self.advertiser_address);
262        buf[8] = self.advertising_sid.value();
263        self.broadcast_id.encode(&mut buf[9..12])?;
264        buf[12] = u8::from(self.pa_sync);
265        buf[13..15].copy_from_slice(&self.pa_interval.0.to_le_bytes());
266        buf[15] = self
267            .subgroups
268            .len()
269            .try_into()
270            .map_err(|_| PacketError::InvalidParameter("Num_Subgroups".to_string()))?;
271        let mut idx = 16;
272        for s in &self.subgroups {
273            s.encode(&mut buf[idx..])?;
274            idx += s.encoded_len();
275        }
276        Ok(())
277    }
278
279    fn encoded_len(&self) -> core::primitive::usize {
280        Self::MIN_PACKET_SIZE + self.subgroups.iter().fold(0, |acc, g| acc + g.encoded_len())
281    }
282}
283
284/// See Broadcast Audio Scan Service spec v1.0 Section 3.1.1.5 for details.
285#[derive(Debug, PartialEq)]
286pub struct ModifySourceOperation {
287    source_id: SourceId,
288    pa_sync: PaSync,
289    pa_interval: PeriodicAdvertisingInterval,
290    subgroups: Vec<BigSubgroup>,
291}
292
293impl ModifySourceOperation {
294    const MIN_PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE
295        + SOURCE_ID_BYTE_SIZE
296        + PA_SYNC_BYTE_SIZE
297        + PeriodicAdvertisingInterval::BYTE_SIZE
298        + NUM_SUBGROUPS_BYTE_SIZE;
299
300    pub fn new(
301        source_id: SourceId,
302        pa_sync: PaSync,
303        pa_interval: PeriodicAdvertisingInterval,
304        subgroups: Vec<BigSubgroup>,
305    ) -> Self {
306        ModifySourceOperation { source_id, pa_sync, pa_interval, subgroups }
307    }
308}
309
310impl ControlPointOperation for ModifySourceOperation {
311    fn opcode() -> ControlPointOpcode {
312        ControlPointOpcode::ModifySource
313    }
314}
315
316impl Decodable for ModifySourceOperation {
317    type Error = PacketError;
318
319    // Min size includes Source_ID, PA_Sync, PA_Interval, and Num_Subgroups params.
320    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
321        if buf.len() < Self::MIN_PACKET_SIZE {
322            return (Err(PacketError::UnexpectedDataLength), buf.len());
323        }
324        let decode_fn = || {
325            let _ = Self::check_opcode(buf[0])?;
326            let source_id = buf[1];
327            let pa_sync = PaSync::try_from(buf[2])?;
328            let pa_interval =
329                PeriodicAdvertisingInterval(u16::from_le_bytes(buf[3..5].try_into().unwrap()));
330            let num_subgroups = buf[5] as usize;
331            let mut subgroups = Vec::new();
332
333            let mut idx = 6;
334            for _i in 0..num_subgroups {
335                if buf.len() < idx + BigSubgroup::MIN_PACKET_SIZE {
336                    return Err(PacketError::UnexpectedDataLength);
337                }
338                let decoded = BigSubgroup::decode(&buf[idx..]);
339                subgroups.push(decoded.0?);
340                idx += decoded.1;
341            }
342            Ok((Self { source_id, pa_sync, pa_interval, subgroups }, idx))
343        };
344
345        match decode_fn() {
346            Ok((obj, consumed)) => (Ok(obj), consumed),
347            Err(e) => (Err(e), buf.len()),
348        }
349    }
350}
351
352impl Encodable for ModifySourceOperation {
353    type Error = PacketError;
354
355    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
356        if buf.len() < self.encoded_len() {
357            return Err(PacketError::BufferTooSmall);
358        }
359
360        buf[0] = Self::opcode() as u8;
361        buf[1] = self.source_id;
362        buf[2] = u8::from(self.pa_sync);
363        buf[3..5].copy_from_slice(&self.pa_interval.0.to_le_bytes());
364        buf[5] = self
365            .subgroups
366            .len()
367            .try_into()
368            .map_err(|_| PacketError::InvalidParameter("Num_Subgroups".to_string()))?;
369        let mut idx = 6;
370        for s in &self.subgroups {
371            s.encode(&mut buf[idx..])?;
372            idx += s.encoded_len();
373        }
374        Ok(())
375    }
376
377    fn encoded_len(&self) -> core::primitive::usize {
378        Self::MIN_PACKET_SIZE + self.subgroups.iter().fold(0, |acc, g| acc + g.encoded_len())
379    }
380}
381
382/// See Broadcast Audio Scan Service spec v1.0 Section 3.1.1.6 for details.
383#[derive(Debug, PartialEq)]
384pub struct SetBroadcastCodeOperation {
385    source_id: SourceId,
386    broadcast_code: [u8; 16],
387}
388
389impl SetBroadcastCodeOperation {
390    const BROADCAST_CODE_LEN: usize = 16;
391    const PACKET_SIZE: usize =
392        ControlPointOpcode::BYTE_SIZE + SOURCE_ID_BYTE_SIZE + Self::BROADCAST_CODE_LEN;
393
394    pub fn new(source_id: SourceId, broadcast_code: [u8; 16]) -> Self {
395        SetBroadcastCodeOperation { source_id, broadcast_code }
396    }
397}
398
399impl ControlPointOperation for SetBroadcastCodeOperation {
400    fn opcode() -> ControlPointOpcode {
401        ControlPointOpcode::SetBroadcastCode
402    }
403}
404
405impl Decodable for SetBroadcastCodeOperation {
406    type Error = PacketError;
407
408    // Min size includes Source_ID, PA_Sync, PA_Interval, and Num_Subgroups params.
409    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
410        if buf.len() < Self::PACKET_SIZE {
411            return (Err(PacketError::UnexpectedDataLength), buf.len());
412        }
413        let decode_fn = || {
414            let _ = Self::check_opcode(buf[0])?;
415            let source_id = buf[1];
416            let mut broadcast_code = [0; Self::BROADCAST_CODE_LEN];
417            broadcast_code.copy_from_slice(&buf[2..2 + Self::BROADCAST_CODE_LEN]);
418            Ok((Self { source_id, broadcast_code }, Self::PACKET_SIZE))
419        };
420
421        match decode_fn() {
422            Ok((obj, consumed)) => (Ok(obj), consumed),
423            Err(e) => (Err(e), buf.len()),
424        }
425    }
426}
427
428impl Encodable for SetBroadcastCodeOperation {
429    type Error = PacketError;
430
431    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
432        if buf.len() < self.encoded_len() {
433            return Err(PacketError::BufferTooSmall);
434        }
435
436        buf[0] = Self::opcode() as u8;
437        buf[1] = self.source_id;
438        buf[2..2 + Self::BROADCAST_CODE_LEN].copy_from_slice(&self.broadcast_code);
439        Ok(())
440    }
441
442    fn encoded_len(&self) -> core::primitive::usize {
443        Self::PACKET_SIZE
444    }
445}
446
447/// See Broadcast Audio Scan Service spec v1.0 Section 3.1.1.7 for details.
448#[derive(Debug, PartialEq)]
449pub struct RemoveSourceOperation(SourceId);
450
451impl RemoveSourceOperation {
452    const PACKET_SIZE: usize = ControlPointOpcode::BYTE_SIZE + SOURCE_ID_BYTE_SIZE;
453
454    pub fn new(source_id: SourceId) -> Self {
455        RemoveSourceOperation(source_id)
456    }
457}
458
459impl ControlPointOperation for RemoveSourceOperation {
460    fn opcode() -> ControlPointOpcode {
461        ControlPointOpcode::RemoveSource
462    }
463}
464
465impl Decodable for RemoveSourceOperation {
466    type Error = PacketError;
467
468    // Min size includes Source_ID, PA_Sync, PA_Interval, and Num_Subgroups params.
469    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
470        if buf.len() < Self::PACKET_SIZE {
471            return (Err(PacketError::UnexpectedDataLength), buf.len());
472        }
473        let decode_fn = || {
474            let _ = Self::check_opcode(buf[0])?;
475            let source_id = buf[1];
476            Ok((RemoveSourceOperation(source_id), Self::PACKET_SIZE))
477        };
478        match decode_fn() {
479            Ok((obj, consumed)) => (Ok(obj), consumed),
480            Err(e) => (Err(e), buf.len()),
481        }
482    }
483}
484
485impl Encodable for RemoveSourceOperation {
486    type Error = PacketError;
487
488    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
489        if buf.len() < self.encoded_len() {
490            return Err(PacketError::BufferTooSmall);
491        }
492
493        buf[0] = Self::opcode() as u8;
494        buf[1] = self.0;
495        Ok(())
496    }
497
498    fn encoded_len(&self) -> core::primitive::usize {
499        Self::PACKET_SIZE
500    }
501}
502
503decodable_enum! {
504    pub enum PaSync<u8, bt_common::packet_encoding::Error, OutOfRange> {
505        DoNotSync = 0x00,
506        SyncPastAvailable = 0x01,
507        SyncPastUnavailable = 0x02,
508    }
509}
510
511impl FromStr for PaSync {
512    type Err = PacketError;
513
514    fn from_str(s: &str) -> Result<Self, Self::Err> {
515        match s {
516            "PaSyncOff" => Ok(PaSync::DoNotSync),
517            "PaSyncPast" => Ok(PaSync::SyncPastAvailable),
518            "PaSyncNoPast" => Ok(PaSync::SyncPastUnavailable),
519            _ => Err(PacketError::InvalidParameter(format!("invalid pa_sync: {s}"))),
520        }
521    }
522}
523
524/// 4-octet bitfield. Bit 0-30 = BIS_index[1-31]
525/// 0x00000000: 0b0 = Do not synchronize to BIS_index[x]
526/// 0xxxxxxxxx: 0b1 = Synchronize to BIS_index[x]
527/// 0xFFFFFFFF: means No preference if used in BroadcastAudioScanControlPoint,
528///             Failed to sync if used in ReceiveState.
529#[derive(Clone, Debug, PartialEq)]
530pub struct BisSync(u32);
531
532impl BisSync {
533    const BYTE_SIZE: usize = 4;
534    const NO_PREFERENCE: u32 = 0xFFFFFFFF;
535
536    /// Creates a new BisSync that doens't synchronzie to any BISes.
537    pub fn no_sync() -> BisSync {
538        BisSync(0)
539    }
540
541    /// Updates the specified BIS index to be synchronized.
542    /// Doesn't touch the synchronize value of other BIS indices.
543    ///
544    /// # Arguments
545    ///
546    /// * `bis_index` - BIS index as defined in the spec. Range should be [1,
547    ///   31]. The specified BIS index will be set to synchronized (0b1).
548    pub fn synchronize_to_index(&mut self, bis_index: BisIndex) -> Result<(), PacketError> {
549        if bis_index < 1 || bis_index > 31 {
550            return Err(PacketError::OutOfRange);
551        }
552        let bit_mask = 0b1 << (bis_index - 1);
553
554        if self.0 == Self::NO_PREFERENCE {
555            // No preference should be re-set to 0 so that all subsequent bit_mask
556            // operations correctly set the bits for the specified `bis_index`.
557            // See BASS v1.0.1 Section 3.1.1.4 Table 3.5.
558            self.0 = 0;
559        }
560        self.0 |= bit_mask;
561        Ok(())
562    }
563
564    /// Creates a BisSync value with the specified BIS indices set to be
565    /// synchronized.
566    ///
567    /// # Arguments
568    ///
569    /// * `bis_indices` - A vector of BIS indices to synchronize to.
570    pub fn sync(bis_indices: Vec<BisIndex>) -> Result<Self, PacketError> {
571        let mut new_sync = Self::no_sync();
572        for bis_index in bis_indices {
573            new_sync.synchronize_to_index(bis_index)?;
574        }
575        Ok(new_sync)
576    }
577}
578
579impl Default for BisSync {
580    fn default() -> Self {
581        Self(Self::NO_PREFERENCE)
582    }
583}
584
585impl From<BisSync> for u32 {
586    fn from(bis_sync: BisSync) -> u32 {
587        bis_sync.0
588    }
589}
590
591#[derive(Clone, Debug, PartialEq)]
592pub struct BigSubgroup {
593    pub(crate) bis_sync: BisSync,
594    pub(crate) metadata: Vec<Metadata>,
595}
596
597impl BigSubgroup {
598    const METADATA_LENGTH_BYTE_SIZE: usize = 1;
599    const MIN_PACKET_SIZE: usize = BisSync::BYTE_SIZE + Self::METADATA_LENGTH_BYTE_SIZE;
600
601    pub fn new(bis_sync: Option<BisSync>) -> Self {
602        Self { bis_sync: bis_sync.unwrap_or_default(), metadata: vec![] }
603    }
604
605    pub fn with_metadata(mut self, metadata: Vec<Metadata>) -> Self {
606        self.metadata = metadata;
607        self
608    }
609}
610
611impl Decodable for BigSubgroup {
612    type Error = PacketError;
613
614    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
615        if buf.len() < BigSubgroup::MIN_PACKET_SIZE {
616            return (Err(PacketError::UnexpectedDataLength), buf.len());
617        }
618        let decode_fn = || {
619            let bis_sync = u32::from_le_bytes(buf[0..4].try_into().unwrap());
620            let metadata_len = buf[4] as usize;
621
622            let mut start_idx = 5;
623            if buf.len() < start_idx + metadata_len {
624                return Err(PacketError::UnexpectedDataLength);
625            }
626
627            let (results_metadata, consumed_len) =
628                Metadata::decode_all(&buf[start_idx..start_idx + metadata_len]);
629            start_idx += consumed_len;
630            if start_idx != 5 + metadata_len {
631                return Err(PacketError::UnexpectedDataLength);
632            }
633            // Ignore any undecodable metadata types
634            let metadata = results_metadata.into_iter().filter_map(Result::ok).collect();
635            Ok((BigSubgroup { bis_sync: BisSync(bis_sync), metadata }, start_idx))
636        };
637        match decode_fn() {
638            Ok((obj, consumed)) => (Ok(obj), consumed),
639            Err(e) => (Err(e), buf.len()),
640        }
641    }
642}
643
644impl Encodable for BigSubgroup {
645    type Error = PacketError;
646
647    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
648        if buf.len() < self.encoded_len() {
649            return Err(PacketError::BufferTooSmall);
650        }
651
652        buf[0..4].copy_from_slice(&u32::from(self.bis_sync.clone()).to_le_bytes());
653        let metadata_len = self
654            .metadata
655            .iter()
656            .fold(0, |acc, m| acc + m.encoded_len())
657            .try_into()
658            .map_err(|_| PacketError::InvalidParameter("Metadata".to_string()))?;
659        buf[4] = metadata_len;
660        let mut next_idx = 5;
661        for m in &self.metadata {
662            m.encode(&mut buf[next_idx..])
663                .map_err(|e| PacketError::InvalidParameter(format!("{e}")))?;
664            next_idx += m.encoded_len();
665        }
666        Ok(())
667    }
668
669    fn encoded_len(&self) -> core::primitive::usize {
670        Self::MIN_PACKET_SIZE + self.metadata.iter().map(Encodable::encoded_len).sum::<usize>()
671    }
672}
673
674/// Broadcast Receive State characteristic as defined in
675/// Broadcast Audio Scan Service spec v1.0 Section 3.2.
676/// The Broadcast Receive State characteristic is used by the server to expose
677/// information about a Broadcast Source. If the server has not written a
678/// Source_ID value to the Broadcast Receive State characteristic, the Broadcast
679/// Recieve State characteristic value shall be empty.
680#[derive(Clone, Debug, PartialEq)]
681pub enum BroadcastReceiveState {
682    Empty,
683    NonEmpty(ReceiveState),
684}
685
686impl BroadcastReceiveState {
687    pub fn is_empty(&self) -> bool {
688        *self == BroadcastReceiveState::Empty
689    }
690
691    pub fn broadcast_id(&self) -> Option<BroadcastId> {
692        match self {
693            BroadcastReceiveState::Empty => None,
694            BroadcastReceiveState::NonEmpty(state) => Some(state.broadcast_id),
695        }
696    }
697
698    pub fn has_same_broadcast_id(&self, other: &BroadcastReceiveState) -> bool {
699        match self {
700            BroadcastReceiveState::Empty => false,
701            BroadcastReceiveState::NonEmpty(this) => match other {
702                BroadcastReceiveState::Empty => false,
703                BroadcastReceiveState::NonEmpty(that) => this.broadcast_id == that.broadcast_id,
704            },
705        }
706    }
707}
708
709impl Decodable for BroadcastReceiveState {
710    type Error = PacketError;
711
712    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
713        if buf.len() == 0 {
714            return (Ok(Self::Empty), 0);
715        }
716        match ReceiveState::decode(&buf[..]) {
717            (Ok(state), consumed) => (Ok(Self::NonEmpty(state)), consumed),
718            (Err(e), consumed) => (Err(e), consumed),
719        }
720    }
721}
722
723impl Encodable for BroadcastReceiveState {
724    type Error = PacketError;
725
726    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
727        match self {
728            Self::Empty => Ok(()),
729            Self::NonEmpty(state) => state.encode(&mut buf[..]),
730        }
731    }
732
733    fn encoded_len(&self) -> core::primitive::usize {
734        match self {
735            Self::Empty => 0,
736            Self::NonEmpty(state) => state.encoded_len(),
737        }
738    }
739}
740
741#[derive(Clone, Debug, PartialEq)]
742pub struct ReceiveState {
743    pub(crate) source_id: SourceId,
744    pub(crate) source_address_type: AddressType,
745    // Address in little endian.
746    pub(crate) source_address: [u8; ADDRESS_BYTE_SIZE],
747    pub(crate) source_adv_sid: AdvertisingSetId,
748    pub(crate) broadcast_id: BroadcastId,
749    pub(crate) pa_sync_state: PaSyncState,
750    // Represents BIG_Encryption param with optional Bad_Code param.
751    pub(crate) big_encryption: EncryptionStatus,
752    pub(crate) subgroups: Vec<BigSubgroup>,
753}
754
755impl ReceiveState {
756    const MIN_PACKET_SIZE: usize = SOURCE_ID_BYTE_SIZE
757        + AddressType::BYTE_SIZE
758        + ADDRESS_BYTE_SIZE
759        + AdvertisingSetId::BYTE_SIZE
760        + BroadcastId::BYTE_SIZE
761        + PA_SYNC_BYTE_SIZE
762        + EncryptionStatus::MIN_PACKET_SIZE
763        + NUM_SUBGROUPS_BYTE_SIZE;
764
765    #[cfg(any(test, feature = "test-utils"))]
766    pub fn new(
767        source_id: u8,
768        source_address_type: AddressType,
769        source_address: [u8; ADDRESS_BYTE_SIZE],
770        source_adv_sid: AdvertisingSetId,
771        broadcast_id: BroadcastId,
772        pa_sync_state: PaSyncState,
773        big_encryption: EncryptionStatus,
774        subgroups: Vec<BigSubgroup>,
775    ) -> ReceiveState {
776        Self {
777            source_id,
778            source_address_type,
779            source_address,
780            source_adv_sid,
781            broadcast_id,
782            pa_sync_state,
783            big_encryption,
784            subgroups,
785        }
786    }
787
788    pub fn pa_sync_state(&self) -> PaSyncState {
789        self.pa_sync_state
790    }
791
792    pub fn big_encryption(&self) -> EncryptionStatus {
793        self.big_encryption
794    }
795
796    pub fn broadcast_id(&self) -> BroadcastId {
797        self.broadcast_id
798    }
799
800    pub fn source_id(&self) -> SourceId {
801        self.source_id
802    }
803}
804
805impl Decodable for ReceiveState {
806    type Error = PacketError;
807
808    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
809        if buf.len() < Self::MIN_PACKET_SIZE {
810            return (Err(PacketError::UnexpectedDataLength), buf.len());
811        }
812
813        let decode_fn = || {
814            let source_id = buf[0];
815            let source_address_type = AddressType::try_from(buf[1])?;
816            let mut source_address = [0; ADDRESS_BYTE_SIZE];
817            source_address.clone_from_slice(&buf[2..8]);
818            let source_adv_sid = AdvertisingSetId::try_from(buf[8])?;
819            let broadcast_id = BroadcastId::decode(&buf[9..12]).0?;
820            let pa_sync_state = PaSyncState::try_from(buf[12])?;
821
822            let big_encryption;
823            let mut idx = 13;
824            match EncryptionStatus::decode(&buf[13..]) {
825                (Ok(encryption), consumed) => {
826                    big_encryption = encryption;
827                    idx += consumed;
828                }
829                (Err(e), _) => {
830                    return Err(e);
831                }
832            }
833            if buf.len() <= idx {
834                return Err(PacketError::UnexpectedDataLength);
835            }
836            let num_subgroups = buf[idx] as usize;
837            let mut subgroups = Vec::new();
838            idx += 1;
839            for _i in 0..num_subgroups {
840                if buf.len() <= idx {
841                    return Err(PacketError::UnexpectedDataLength);
842                }
843                let (subgroup, consumed) = BigSubgroup::decode(&buf[idx..]);
844                subgroups.push(subgroup?);
845                idx += consumed;
846            }
847            Ok((
848                ReceiveState {
849                    source_id,
850                    source_address_type,
851                    source_address,
852                    source_adv_sid,
853                    broadcast_id,
854                    pa_sync_state,
855                    big_encryption,
856                    subgroups,
857                },
858                idx,
859            ))
860        };
861        match decode_fn() {
862            Ok((obj, consumed)) => (Ok(obj), consumed),
863            Err(e) => (Err(e), buf.len()),
864        }
865    }
866}
867
868impl Encodable for ReceiveState {
869    type Error = PacketError;
870
871    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
872        if buf.len() < self.encoded_len() {
873            return Err(PacketError::BufferTooSmall);
874        }
875
876        buf[0] = self.source_id;
877        buf[1] = self.source_address_type as u8;
878        buf[2..8].copy_from_slice(&self.source_address);
879        buf[8] = self.source_adv_sid.value();
880        self.broadcast_id.encode(&mut buf[9..12])?;
881        buf[12] = u8::from(self.pa_sync_state);
882        let mut idx = 13 + self.big_encryption.encoded_len();
883        self.big_encryption.encode(&mut buf[13..idx])?;
884        buf[idx] = self
885            .subgroups
886            .len()
887            .try_into()
888            .map_err(|_| PacketError::InvalidParameter("Metadata".to_string()))?;
889        idx += 1;
890        for s in &self.subgroups {
891            s.encode(&mut buf[idx..])?;
892            idx += s.encoded_len();
893        }
894        Ok(())
895    }
896
897    fn encoded_len(&self) -> core::primitive::usize {
898        // Length including Source_ID, Source_Address_Type, Source_Address,
899        // Source_Adv_SID, Broadcast_ID, PA_Sync_State, BIG_Encryption, Bad_Code,
900        // Num_Subgroups and subgroup-related params.
901        SOURCE_ID_BYTE_SIZE
902            + AddressType::BYTE_SIZE
903            + self.source_address.len()
904            + AdvertisingSetId::BYTE_SIZE
905            + self.broadcast_id.encoded_len()
906            + PA_SYNC_BYTE_SIZE
907            + self.big_encryption.encoded_len()
908            + NUM_SUBGROUPS_BYTE_SIZE
909            + self.subgroups.iter().map(Encodable::encoded_len).sum::<usize>()
910    }
911}
912
913decodable_enum! {
914    pub enum PaSyncState<u8, bt_common::packet_encoding::Error, OutOfRange> {
915        NotSynced = 0x00,
916        SyncInfoRequest = 0x01,
917        Synced = 0x02,
918        FailedToSync = 0x03,
919        NoPast = 0x04,
920    }
921}
922
923/// Represents BIG_Encryption and Bad_Code params from BASS spec v.1.0 Table
924/// 3.9.
925#[derive(Clone, Copy, Debug, PartialEq)]
926pub enum EncryptionStatus {
927    NotEncrypted,
928    BroadcastCodeRequired,
929    Decrypting,
930    BadCode([u8; 16]),
931}
932
933impl EncryptionStatus {
934    // Should at least include the BIG_Encryption enum value which is 1 byte long.
935    const MIN_PACKET_SIZE: usize = 1;
936
937    // Returns the u8 value that represents the status of encryption
938    // as described for BIG_Encryption parameter.
939    pub const fn raw_value(self) -> u8 {
940        match self {
941            EncryptionStatus::NotEncrypted => 0x00,
942            EncryptionStatus::BroadcastCodeRequired => 0x01,
943            EncryptionStatus::Decrypting => 0x02,
944            EncryptionStatus::BadCode(_) => 0x03,
945        }
946    }
947}
948
949impl Decodable for EncryptionStatus {
950    type Error = PacketError;
951
952    fn decode(buf: &[u8]) -> (core::result::Result<Self, Self::Error>, usize) {
953        if buf.len() < 1 {
954            return (Err(PacketError::UnexpectedDataLength), buf.len());
955        }
956        match buf[0] {
957            0x00 => (Ok(Self::NotEncrypted), 1),
958            0x01 => (Ok(Self::BroadcastCodeRequired), 1),
959            0x02 => (Ok(Self::Decrypting), 1),
960            0x03 => {
961                if buf.len() < 17 {
962                    return (Err(PacketError::UnexpectedDataLength), buf.len());
963                }
964                (Ok(Self::BadCode(buf[1..17].try_into().unwrap())), 17)
965            }
966            _ => (Err(PacketError::OutOfRange), buf.len()),
967        }
968    }
969}
970
971impl Encodable for EncryptionStatus {
972    type Error = PacketError;
973
974    fn encode(&self, buf: &mut [u8]) -> core::result::Result<(), Self::Error> {
975        if buf.len() < self.encoded_len() {
976            return Err(PacketError::BufferTooSmall);
977        }
978
979        buf[0] = self.raw_value();
980        match self {
981            EncryptionStatus::BadCode(code) => buf[1..17].copy_from_slice(code),
982            _ => {}
983        }
984        Ok(())
985    }
986
987    fn encoded_len(&self) -> core::primitive::usize {
988        match self {
989            // For Bad_Code value, we also have to encrypt the incorrect
990            // 16-octet Broadcast_Code. See BASS spec Table 3.9.
991            EncryptionStatus::BadCode(_) => 1 + 16,
992            _ => 1,
993        }
994    }
995}
996
997#[cfg(test)]
998mod tests {
999    use super::*;
1000
1001    use bt_common::generic_audio::ContextType;
1002
1003    #[test]
1004    fn encryption_status_enum() {
1005        let not_encrypted = EncryptionStatus::NotEncrypted;
1006        let encrypted = EncryptionStatus::BroadcastCodeRequired;
1007        let decrypting = EncryptionStatus::Decrypting;
1008        let bad_code = EncryptionStatus::BadCode([
1009            0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1010            0x02, 0x01,
1011        ]);
1012
1013        assert_eq!(0x00, not_encrypted.raw_value());
1014        assert_eq!(0x01, encrypted.raw_value());
1015        assert_eq!(0x02, decrypting.raw_value());
1016        assert_eq!(0x03, bad_code.raw_value());
1017    }
1018
1019    #[test]
1020    fn encryption_status() {
1021        // Encoding not encrypted status.
1022        let not_encrypted = EncryptionStatus::NotEncrypted;
1023        assert_eq!(not_encrypted.encoded_len(), 1);
1024        let mut buf = vec![0; not_encrypted.encoded_len()];
1025        let _ = not_encrypted.encode(&mut buf[..]).expect("should not fail");
1026
1027        let bytes = vec![0x00];
1028        assert_eq!(buf, bytes);
1029
1030        // Decoding not encrypted.
1031        let (decoded, len) = EncryptionStatus::decode(&bytes);
1032        assert_eq!(decoded, Ok(not_encrypted));
1033        assert_eq!(len, 1);
1034
1035        // Encoding bad code status with code.
1036        let bad_code = EncryptionStatus::BadCode([
1037            0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1038            0x02, 0x01,
1039        ]);
1040        assert_eq!(bad_code.encoded_len(), 17);
1041        let mut buf = vec![0; bad_code.encoded_len()];
1042        let _ = bad_code.encode(&mut buf[..]).expect("should not fail");
1043
1044        let bytes = vec![
1045            0x03, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
1046            0x03, 0x02, 0x01,
1047        ];
1048        assert_eq!(buf, bytes);
1049
1050        // Decoding bad code statsu with code.
1051        let (decoded, len) = EncryptionStatus::decode(&bytes);
1052        assert_eq!(decoded, Ok(bad_code));
1053        assert_eq!(len, 17);
1054    }
1055
1056    #[test]
1057    fn invalid_encryption_status() {
1058        // Cannot encode into empty buffer.
1059        let not_encrypted = EncryptionStatus::NotEncrypted;
1060        let mut buf = vec![];
1061        let _ = not_encrypted.encode(&mut buf[..]).expect_err("should fail");
1062
1063        // Not enough buffer space for encoding.
1064        let bad_code = EncryptionStatus::BadCode([
1065            0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1066            0x02, 0x01,
1067        ]);
1068        let mut buf = vec![0; 1];
1069        let _ = bad_code.encode(&mut buf[..]).expect_err("should fail");
1070
1071        // Cannot decode empty buffer.
1072        let buf = vec![];
1073        let _ = EncryptionStatus::decode(&buf).0.expect_err("should fail");
1074
1075        // Bad code status with no code.
1076        let buf = vec![0x03];
1077        let _ = EncryptionStatus::decode(&buf).0.expect_err("should fail");
1078    }
1079
1080    #[test]
1081    fn bis_sync_sync() {
1082        let bis_sync = BisSync::sync(vec![1, 6, 31]).expect("should succeed");
1083        assert_eq!(u32::from(bis_sync), 0x40000021);
1084
1085        let bis_sync_empty = BisSync::sync(vec![]).expect("should succeed");
1086        assert_eq!(u32::from(bis_sync_empty), 0);
1087    }
1088
1089    #[test]
1090    fn invalid_bis_sync() {
1091        BisSync::sync(vec![0]).expect_err("should fail");
1092        BisSync::sync(vec![32]).expect_err("should fail");
1093    }
1094
1095    #[test]
1096    fn synchronize_to_index() {
1097        let mut bis_sync = BisSync::no_sync();
1098        assert_eq!(u32::from(bis_sync.clone()), 0);
1099
1100        bis_sync.synchronize_to_index(1).expect("should succeed");
1101        assert_eq!(u32::from(bis_sync.clone()), 0x1);
1102
1103        bis_sync.synchronize_to_index(31).expect("should succeed");
1104        assert_eq!(u32::from(bis_sync.clone()), 0x40000001);
1105
1106        bis_sync.synchronize_to_index(0).expect_err("should fail");
1107        bis_sync.synchronize_to_index(32).expect_err("should fail");
1108    }
1109
1110    #[test]
1111    fn synchronize_to_index_from_default() {
1112        let mut bis_sync_default = BisSync::default();
1113        assert_eq!(u32::from(bis_sync_default.clone()), 0xFFFFFFFF);
1114
1115        // An initial synchronization of no preference should correctly be set with the
1116        // requested index.
1117        bis_sync_default.synchronize_to_index(1).expect("should succeed");
1118        assert_eq!(u32::from(bis_sync_default.clone()), 0x1);
1119
1120        // Additional index should be accumulated correctly.
1121        bis_sync_default.synchronize_to_index(6).expect("should succeed");
1122        assert_eq!(u32::from(bis_sync_default), 0x21);
1123    }
1124
1125    #[test]
1126    fn pa_sync_from_str() {
1127        let sync = PaSync::from_str("PaSyncOff").expect("should succeed");
1128        assert_eq!(sync, PaSync::DoNotSync);
1129        let sync = PaSync::from_str("PaSyncPast").expect("should succeed");
1130        assert_eq!(sync, PaSync::SyncPastAvailable);
1131        let sync = PaSync::from_str("PaSyncNoPast").expect("should succeed");
1132        assert_eq!(sync, PaSync::SyncPastUnavailable);
1133        PaSync::from_str("invalid").expect_err("should fail");
1134    }
1135
1136    #[test]
1137    fn remote_scan_stopped() {
1138        // Encoding remote scan stopped.
1139        let stopped = RemoteScanStoppedOperation;
1140        assert_eq!(stopped.encoded_len(), 1);
1141        let mut buf = vec![0u8; stopped.encoded_len()];
1142        stopped.encode(&mut buf[..]).expect("shoud succeed");
1143
1144        let bytes = vec![0x00];
1145        assert_eq!(buf, bytes);
1146
1147        // Decoding remote scan stopped.
1148        let (decoded, len) = RemoteScanStoppedOperation::decode(&bytes);
1149        assert_eq!(decoded, Ok(stopped));
1150        assert_eq!(len, 1);
1151        assert_eq!(
1152            RemoteScanStoppedOperation::decode(&[]).0,
1153            Err(PacketError::UnexpectedDataLength)
1154        );
1155    }
1156
1157    #[test]
1158    fn remote_scan_started() {
1159        // Encoding remote scan started.
1160        let started = RemoteScanStartedOperation;
1161        assert_eq!(started.encoded_len(), 1);
1162        let mut buf = vec![0u8; started.encoded_len()];
1163        started.encode(&mut buf[..]).expect("shoud succeed");
1164
1165        let bytes = vec![0x01];
1166        assert_eq!(buf, vec![0x01]);
1167
1168        // Decoding remote scan started.
1169        let (decoded, len) = RemoteScanStartedOperation::decode(&bytes);
1170        assert_eq!(decoded, Ok(started));
1171        assert_eq!(len, 1);
1172    }
1173
1174    #[test]
1175    fn add_source_without_subgroups() {
1176        // Encoding operation with no subgroups.
1177        let op = AddSourceOperation::new(
1178            AddressType::Public,
1179            [0x04, 0x10, 0x00, 0x00, 0x00, 0x00],
1180            AdvertisingSetId::try_from(1).unwrap(),
1181            BroadcastId::try_from(0x11).unwrap(),
1182            PaSync::DoNotSync,
1183            PeriodicAdvertisingInterval::unknown(),
1184            vec![],
1185        );
1186        assert_eq!(op.encoded_len(), 16);
1187        let mut buf = vec![0u8; op.encoded_len()];
1188        op.encode(&mut buf[..]).expect("shoud succeed");
1189
1190        let bytes = vec![
1191            0x02, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x00, 0xFF,
1192            0xFF, 0x00,
1193        ];
1194        assert_eq!(buf, bytes);
1195
1196        // Decoding operation with no subgroups.
1197        let (decoded, len) = AddSourceOperation::decode(&bytes);
1198        assert_eq!(decoded, Ok(op));
1199        assert_eq!(len, 16);
1200    }
1201
1202    #[test]
1203    fn add_source_with_subgroups() {
1204        // Encoding operation with subgroups.
1205        let subgroups = vec![BigSubgroup::new(None).with_metadata(vec![
1206            Metadata::PreferredAudioContexts(vec![ContextType::Media, ContextType::Game]), // encoded_len = 4
1207            Metadata::ProgramInfo("test".to_string()), // encoded_len = 6
1208        ])];
1209        let op = AddSourceOperation::new(
1210            AddressType::Random,
1211            [0x04, 0x10, 0x00, 0x00, 0x00, 0x00],
1212            AdvertisingSetId::try_from(1).unwrap(),
1213            BroadcastId::try_from(0x11).unwrap(),
1214            PaSync::SyncPastAvailable,
1215            PeriodicAdvertisingInterval::unknown(),
1216            subgroups,
1217        );
1218        assert_eq!(op.encoded_len(), 31); // 16 for minimum params and params 15 for the subgroup.
1219        let mut buf = vec![0u8; op.encoded_len()];
1220        op.encode(&mut buf[..]).expect("shoud succeed");
1221
1222        let bytes = vec![
1223            0x02, 0x01, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x00, 0x01, 0xFF,
1224            0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, // BIS_Sync, Metdata_Length
1225            0x03, 0x01, 0x0C, 0x00, // Preferred_Audio_Contexts metadata
1226            0x05, 0x03, 0x74, 0x65, 0x73, 0x074, // Program_Info metadata
1227        ];
1228        assert_eq!(buf, bytes);
1229
1230        // Decoding operation with subgroups.
1231        let (decoded, len) = AddSourceOperation::decode(&bytes);
1232        assert_eq!(decoded, Ok(op));
1233        assert_eq!(len, 31);
1234    }
1235
1236    #[test]
1237    fn invalid_advertising_sid_decoding() {
1238        // AddSourceOperation with invalid Advertising_SID (0x10 > 0x0F)
1239        let invalid_add_source_bytes = vec![
1240            0x02, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x00, 0x00, 0x00, 0xFF,
1241            0xFF, 0x00,
1242        ];
1243        let (decoded, _) = AddSourceOperation::decode(&invalid_add_source_bytes);
1244        assert_eq!(decoded, Err(PacketError::OutOfRange));
1245
1246        // ReceiveState with invalid Advertising_SID (0x10 > 0x0F)
1247        let invalid_receive_state_bytes = vec![
1248            0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x10, 0x03, 0x02, 0x01, 0x02, 0x00,
1249            0x00,
1250        ];
1251        let (decoded, _) = BroadcastReceiveState::decode(&invalid_receive_state_bytes);
1252        assert_eq!(decoded, Err(PacketError::OutOfRange));
1253    }
1254
1255    #[test]
1256    fn modify_source_without_subgroups() {
1257        // Encoding operation with no subgroups.
1258        let op = ModifySourceOperation::new(
1259            0x0A,
1260            PaSync::SyncPastAvailable,
1261            PeriodicAdvertisingInterval(0x1004),
1262            vec![],
1263        );
1264        assert_eq!(op.encoded_len(), 6);
1265        let mut buf = vec![0u8; op.encoded_len()];
1266        op.encode(&mut buf[..]).expect("shoud succeed");
1267
1268        let bytes = vec![0x03, 0x0A, 0x01, 0x04, 0x10, 0x00];
1269        assert_eq!(buf, bytes);
1270
1271        // Decoding operation with no subgroups.
1272        let (decoded, len) = ModifySourceOperation::decode(&bytes);
1273        assert_eq!(decoded, Ok(op));
1274        assert_eq!(len, 6);
1275    }
1276
1277    #[test]
1278    fn modify_source_with_subgroups() {
1279        // Encoding operation with subgroups.
1280        let subgroups = vec![
1281            BigSubgroup::new(None).with_metadata(vec![Metadata::ParentalRating(Rating::all_age())]), /* encoded_len = 8 */
1282            BigSubgroup::new(Some(BisSync(0x000000FE)))
1283                .with_metadata(vec![Metadata::BroadcastAudioImmediateRenderingFlag]), /* encoded_len = 7 */
1284        ];
1285        let op = ModifySourceOperation::new(
1286            0x0B,
1287            PaSync::DoNotSync,
1288            PeriodicAdvertisingInterval::unknown(),
1289            subgroups,
1290        );
1291        assert_eq!(op.encoded_len(), 21); // 6 for minimum params and params 15 for two subgroups.
1292        let mut buf = vec![0u8; op.encoded_len()];
1293        op.encode(&mut buf[..]).expect("shoud succeed");
1294
1295        let bytes = vec![
1296            0x03, 0x0B, 0x00, 0xFF, 0xFF, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x02, 0x06,
1297            0x01, // First subgroup.
1298            0xFE, 0x00, 0x00, 0x00, 0x02, 0x01, 0x09, // Second subgroup.
1299        ];
1300        assert_eq!(buf, bytes);
1301
1302        // Decoding operation with subgroups.
1303        let (decoded, len) = ModifySourceOperation::decode(&bytes);
1304        assert_eq!(decoded, Ok(op));
1305        assert_eq!(len, 21);
1306    }
1307
1308    #[test]
1309    fn set_broadcast_code() {
1310        // Encoding.
1311        let op = SetBroadcastCodeOperation::new(
1312            0x0A,
1313            [
1314                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14,
1315                0x15, 0x16,
1316            ],
1317        );
1318        assert_eq!(op.encoded_len(), 18);
1319        let mut buf = vec![0; op.encoded_len()];
1320        op.encode(&mut buf[..]).expect("should succeed");
1321
1322        let bytes = vec![
1323            0x04, 0x0A, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
1324            0x13, 0x14, 0x15, 0x16,
1325        ];
1326        assert_eq!(buf, bytes);
1327
1328        // Decoding.
1329        let (decoded, len) = SetBroadcastCodeOperation::decode(&bytes);
1330        assert_eq!(decoded, Ok(op));
1331        assert_eq!(len, 18);
1332    }
1333
1334    #[test]
1335    fn remove_source() {
1336        // Encoding.
1337        let op = RemoveSourceOperation::new(0x0A);
1338        assert_eq!(op.encoded_len(), 2);
1339        let mut buf = vec![0; op.encoded_len()];
1340        op.encode(&mut buf[..]).expect("should succeed");
1341
1342        let bytes = vec![0x05, 0x0A];
1343        assert_eq!(buf, bytes);
1344
1345        // Decoding.
1346        let (decoded, len) = RemoveSourceOperation::decode(&bytes);
1347        assert_eq!(decoded, Ok(op));
1348        assert_eq!(len, 2);
1349    }
1350
1351    #[test]
1352    fn broadcast_receive_state_without_subgroups() {
1353        // Encoding.
1354        let state = BroadcastReceiveState::NonEmpty(ReceiveState {
1355            source_id: 0x01,
1356            source_address_type: AddressType::Public,
1357            source_address: [0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A],
1358            source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(),
1359            broadcast_id: BroadcastId::try_from(0x00010203).unwrap(),
1360            pa_sync_state: PaSyncState::Synced,
1361            big_encryption: EncryptionStatus::BadCode([
1362                0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x7, 0x06, 0x05, 0x04, 0x03,
1363                0x02, 0x01,
1364            ]),
1365            subgroups: vec![],
1366        });
1367        assert_eq!(state.encoded_len(), 31);
1368        let mut buf = vec![0; state.encoded_len()];
1369        state.encode(&mut buf[..]).expect("should succeed");
1370
1371        let bytes = vec![
1372            0x01, 0x00, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x01, 0x03, 0x02, 0x01, 0x02, 0x03,
1373            0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
1374            0x02, 0x01, // Bad_Code with the code.
1375            0x00,
1376        ];
1377        assert_eq!(buf, bytes);
1378
1379        // Decoding.
1380        let (decoded, len) = BroadcastReceiveState::decode(&bytes);
1381        assert_eq!(decoded, Ok(state));
1382        assert_eq!(len, 31);
1383    }
1384
1385    #[test]
1386    fn broadcast_receive_state_with_subgroups() {
1387        // Encoding
1388        let state = BroadcastReceiveState::NonEmpty(ReceiveState {
1389            source_id: 0x01,
1390            source_address_type: AddressType::Random,
1391            source_address: [0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A],
1392            source_adv_sid: AdvertisingSetId::try_from(0x01).unwrap(),
1393            broadcast_id: BroadcastId::try_from(0x00010203).unwrap(),
1394            pa_sync_state: PaSyncState::NotSynced,
1395            big_encryption: EncryptionStatus::NotEncrypted,
1396            subgroups: vec![BigSubgroup::new(None)
1397                .with_metadata(vec![Metadata::ParentalRating(Rating::AllAge)]) /* encoded_len = 8 */],
1398        });
1399        assert_eq!(state.encoded_len(), 23);
1400        let mut buf = vec![0; state.encoded_len()];
1401        state.encode(&mut buf[..]).expect("should succeed");
1402
1403        let bytes = vec![
1404            0x01, 0x01, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x01, 0x03, 0x02, 0x01, 0x00, 0x00,
1405            0x01, // 1 Subgroup.
1406            0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x02, 0x06, 0x01, // Subgroup.
1407        ];
1408        assert_eq!(buf, bytes);
1409
1410        // Decoding.
1411        let (decoded, len) = BroadcastReceiveState::decode(&bytes);
1412        assert_eq!(decoded, Ok(state));
1413        assert_eq!(len, 23);
1414    }
1415}