blob: 73fea2f789e3fc7f74a96b71f4a8a8bf419e910b [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use fidl_fuchsia_bluetooth_bredr as bredr;
use fuchsia_bluetooth::profile::{DataElement, ProtocolDescriptor};
use crate::dlci::ServerChannel;
/// Returns a ProtocolDescriptorList for an RFCOMM service with the provided `server_channel`.
pub fn build_rfcomm_protocol(server_channel: ServerChannel) -> Vec<ProtocolDescriptor> {
// The PSM for L2CAP is empty when RFCOMM is used.
vec![
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::Rfcomm,
params: vec![DataElement::Uint8(server_channel.into())],
},
]
}
/// Returns true if the provided `protocol` is RFCOMM.
///
/// Protocols are generally specified by a vector of ProtocolDescriptors which
/// are ordered from lowest level (typically L2CAP) to highest.
pub fn is_rfcomm_protocol(protocol: &Vec<ProtocolDescriptor>) -> bool {
protocol.iter().any(|descriptor| descriptor.protocol == bredr::ProtocolIdentifier::Rfcomm)
}
/// Returns the ServerChannel number from the provided `protocol` or None if it
/// does not exist.
pub fn server_channel_from_protocol(protocol: &Vec<ProtocolDescriptor>) -> Option<ServerChannel> {
for descriptor in protocol {
if descriptor.protocol == bredr::ProtocolIdentifier::Rfcomm {
// If the Protocol is RFCOMM, there should be one element with the Server Channel.
if descriptor.params.len() != 1 {
return None;
}
if let DataElement::Uint8(sc) = descriptor.params[0] {
return ServerChannel::try_from(sc).ok();
}
return None;
}
}
None
}
/// Returns the connect parameters for the provided RFCOMM `server_channel`.
pub fn rfcomm_connect_parameters(server_channel: ServerChannel) -> bredr::ConnectParameters {
bredr::ConnectParameters::Rfcomm(bredr::RfcommParameters {
channel: Some(server_channel.into()),
..bredr::RfcommParameters::default()
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn server_channel_from_l2cap_is_none() {
// Just L2CAP - should be no server channel.
let protocol = vec![ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::L2Cap,
params: vec![DataElement::Uint16(bredr::PSM_AVDTP)],
}];
assert_eq!(server_channel_from_protocol(&protocol), None);
}
#[test]
fn server_channel_from_empty_rfcomm_is_none() {
// RFCOMM but un-allocated Server Channel.
let protocol = vec![
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::Rfcomm, params: vec![] },
];
assert_eq!(server_channel_from_protocol(&protocol), None);
}
#[test]
fn server_channel_from_invalid_rfcomm_is_none() {
// RFCOMM but invalidly formatted.
let protocol = vec![
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::Rfcomm,
params: vec![DataElement::Uint16(100)], // Should be Uint8
},
];
assert_eq!(server_channel_from_protocol(&protocol), None);
}
#[test]
fn invalid_server_channel_number_is_none() {
// Valid RFCOMM but ServerChannel number is invalid.
let protocol = vec![
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::Rfcomm,
params: vec![DataElement::Uint8(200)], // Too large
},
];
assert_eq!(server_channel_from_protocol(&protocol), None);
}
#[test]
fn server_channel_from_valid_rfcomm_is_present() {
// RFCOMM service with assigned server channel.
let sc = 10;
let protocol = vec![
ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::Rfcomm,
params: vec![DataElement::Uint8(sc)],
},
];
let expected = ServerChannel::try_from(sc).ok();
assert_eq!(server_channel_from_protocol(&protocol), expected);
}
#[test]
fn server_channel_from_only_rfcomm_protocol_is_present() {
// While unusual, getting the server channel from a protocol descriptor list that only
// contains RFCOMM is ok.
let sc = 12;
let protocol = vec![ProtocolDescriptor {
protocol: bredr::ProtocolIdentifier::Rfcomm,
params: vec![DataElement::Uint8(sc)],
}];
let expected = ServerChannel::try_from(sc).ok();
assert_eq!(server_channel_from_protocol(&protocol), expected);
}
}