bt_rfcomm/
profile.rs

1// Copyright 2021 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 fidl_fuchsia_bluetooth_bredr as bredr;
6use fuchsia_bluetooth::profile::{DataElement, ProtocolDescriptor};
7
8use crate::dlci::ServerChannel;
9
10/// Returns a ProtocolDescriptorList for an RFCOMM service with the provided `server_channel`.
11pub fn build_rfcomm_protocol(server_channel: ServerChannel) -> Vec<ProtocolDescriptor> {
12    // The PSM for L2CAP is empty when RFCOMM is used.
13    vec![
14        ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
15        ProtocolDescriptor {
16            protocol: bredr::ProtocolIdentifier::Rfcomm,
17            params: vec![DataElement::Uint8(server_channel.into())],
18        },
19    ]
20}
21
22/// Returns true if the provided `protocol` is RFCOMM.
23///
24/// Protocols are generally specified by a vector of ProtocolDescriptors which
25/// are ordered from lowest level (typically L2CAP) to highest.
26pub fn is_rfcomm_protocol(protocol: &Vec<ProtocolDescriptor>) -> bool {
27    protocol.iter().any(|descriptor| descriptor.protocol == bredr::ProtocolIdentifier::Rfcomm)
28}
29
30/// Returns the ServerChannel number from the provided `protocol` or None if it
31/// does not exist.
32pub fn server_channel_from_protocol(protocol: &Vec<ProtocolDescriptor>) -> Option<ServerChannel> {
33    for descriptor in protocol {
34        if descriptor.protocol == bredr::ProtocolIdentifier::Rfcomm {
35            // If the Protocol is RFCOMM, there should be one element with the Server Channel.
36            if descriptor.params.len() != 1 {
37                return None;
38            }
39
40            if let DataElement::Uint8(sc) = descriptor.params[0] {
41                return ServerChannel::try_from(sc).ok();
42            }
43            return None;
44        }
45    }
46    None
47}
48
49/// Returns the connect parameters for the provided RFCOMM `server_channel`.
50pub fn rfcomm_connect_parameters(server_channel: ServerChannel) -> bredr::ConnectParameters {
51    bredr::ConnectParameters::Rfcomm(bredr::RfcommParameters {
52        channel: Some(server_channel.into()),
53        ..bredr::RfcommParameters::default()
54    })
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn server_channel_from_l2cap_is_none() {
63        // Just L2CAP - should be no server channel.
64        let protocol = vec![ProtocolDescriptor {
65            protocol: bredr::ProtocolIdentifier::L2Cap,
66            params: vec![DataElement::Uint16(bredr::PSM_AVDTP)],
67        }];
68        assert_eq!(server_channel_from_protocol(&protocol), None);
69    }
70
71    #[test]
72    fn server_channel_from_empty_rfcomm_is_none() {
73        // RFCOMM but un-allocated Server Channel.
74        let protocol = vec![
75            ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
76            ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::Rfcomm, params: vec![] },
77        ];
78        assert_eq!(server_channel_from_protocol(&protocol), None);
79    }
80
81    #[test]
82    fn server_channel_from_invalid_rfcomm_is_none() {
83        // RFCOMM but invalidly formatted.
84        let protocol = vec![
85            ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
86            ProtocolDescriptor {
87                protocol: bredr::ProtocolIdentifier::Rfcomm,
88                params: vec![DataElement::Uint16(100)], // Should be Uint8
89            },
90        ];
91        assert_eq!(server_channel_from_protocol(&protocol), None);
92    }
93
94    #[test]
95    fn invalid_server_channel_number_is_none() {
96        // Valid RFCOMM but ServerChannel number is invalid.
97        let protocol = vec![
98            ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
99            ProtocolDescriptor {
100                protocol: bredr::ProtocolIdentifier::Rfcomm,
101                params: vec![DataElement::Uint8(200)], // Too large
102            },
103        ];
104        assert_eq!(server_channel_from_protocol(&protocol), None);
105    }
106
107    #[test]
108    fn server_channel_from_valid_rfcomm_is_present() {
109        // RFCOMM service with assigned server channel.
110        let sc = 10;
111        let protocol = vec![
112            ProtocolDescriptor { protocol: bredr::ProtocolIdentifier::L2Cap, params: vec![] },
113            ProtocolDescriptor {
114                protocol: bredr::ProtocolIdentifier::Rfcomm,
115                params: vec![DataElement::Uint8(sc)],
116            },
117        ];
118        let expected = ServerChannel::try_from(sc).ok();
119        assert_eq!(server_channel_from_protocol(&protocol), expected);
120    }
121
122    #[test]
123    fn server_channel_from_only_rfcomm_protocol_is_present() {
124        // While unusual, getting the server channel from a protocol descriptor list that only
125        // contains RFCOMM is ok.
126        let sc = 12;
127        let protocol = vec![ProtocolDescriptor {
128            protocol: bredr::ProtocolIdentifier::Rfcomm,
129            params: vec![DataElement::Uint8(sc)],
130        }];
131        let expected = ServerChannel::try_from(sc).ok();
132        assert_eq!(server_channel_from_protocol(&protocol), expected);
133    }
134}