Skip to main content

bt_rfcomm/
lib.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
5/// The direct link connection identifier (DLCI) definitions.
6mod dlci;
7pub use dlci::{DLCI, ServerChannel};
8
9/// The error type used throughout this library.
10mod error;
11pub use error::Error as RfcommError;
12
13/// The definitions for RFCOMM frames - the basic unit of data in RFCOMM.
14pub mod frame;
15
16/// Convenience helpers for the `bredr.Profile` API RFCOMM operations.
17pub mod profile;
18
19/// The Role assigned to a device in an RFCOMM Session.
20#[derive(Copy, Clone, Debug, PartialEq)]
21pub enum Role {
22    /// RFCOMM Session has not started up the start-up procedure.
23    Unassigned,
24    /// The start-up procedure is in progress, and so the role is being negotiated.
25    Negotiating,
26    /// The device that starts up the multiplexer control channel is considered
27    /// the initiator.
28    Initiator,
29    /// The device that responds to the start-up procedure.
30    Responder,
31}
32
33impl Role {
34    /// Returns the Role opposite to the current Role.
35    pub fn opposite_role(&self) -> Self {
36        match self {
37            Role::Initiator => Role::Responder,
38            Role::Responder => Role::Initiator,
39            role => *role,
40        }
41    }
42
43    /// Returns true if the multiplexer has started - namely, a role has been assigned.
44    pub fn is_multiplexer_started(&self) -> bool {
45        *self == Role::Initiator || *self == Role::Responder
46    }
47}
48
49/// Returns the maximum RFCOMM packet size that can be used for the provided L2CAP `mtu`.
50/// It is assumed that `mtu` is a valid L2CAP MTU.
51pub fn max_packet_size_from_l2cap_mtu(mtu: u16) -> u16 {
52    let max_from_mtu = mtu.saturating_sub(crate::frame::MAX_RFCOMM_HEADER_SIZE as u16);
53    std::cmp::min(max_from_mtu, crate::frame::MAX_INFORMATION_LENGTH as u16)
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn test_convert_to_opposite_role() {
62        let role = Role::Initiator;
63        assert_eq!(role.opposite_role(), Role::Responder);
64
65        let role = Role::Responder;
66        assert_eq!(role.opposite_role(), Role::Initiator);
67
68        let role = Role::Unassigned;
69        assert_eq!(role.opposite_role(), Role::Unassigned);
70
71        let role = Role::Negotiating;
72        assert_eq!(role.opposite_role(), Role::Negotiating);
73    }
74
75    #[test]
76    fn max_packet_size_capped_for_large_l2cap_mtu() {
77        let l2cap_mtu = 65535;
78        assert_eq!(max_packet_size_from_l2cap_mtu(l2cap_mtu), 32767);
79    }
80}