1 // Copyright 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Bluetooth Core, Vol 2, Part C, 4.3.4
16
17 use crate::lmp::procedure::Context;
18 use crate::packets::lmp;
19
initiate(ctx: &impl Context, features_page: u8) -> u6420 pub async fn initiate(ctx: &impl Context, features_page: u8) -> u64 {
21 ctx.send_lmp_packet(
22 lmp::FeaturesReqExtBuilder {
23 transaction_id: 0,
24 features_page,
25 max_supported_page: 1,
26 extended_features: ctx.extended_features(features_page).to_le_bytes(),
27 }
28 .build(),
29 );
30
31 u64::from_le_bytes(
32 *ctx.receive_lmp_packet::<lmp::FeaturesResExt>().await.get_extended_features(),
33 )
34 }
35
respond(ctx: &impl Context)36 pub async fn respond(ctx: &impl Context) {
37 let req = ctx.receive_lmp_packet::<lmp::FeaturesReqExt>().await;
38 let features_page = req.get_features_page();
39
40 ctx.send_lmp_packet(
41 lmp::FeaturesResExtBuilder {
42 transaction_id: 0,
43 features_page,
44 max_supported_page: 1,
45 extended_features: ctx.extended_features(features_page).to_le_bytes(),
46 }
47 .build(),
48 );
49 }
50
supported_on_both_page(ctx: &impl Context, page_number: u8, feature_mask: u64) -> bool51 async fn supported_on_both_page(ctx: &impl Context, page_number: u8, feature_mask: u64) -> bool {
52 let local_supported = ctx.extended_features(page_number) & feature_mask != 0;
53 // Lazy peer features
54 let peer_supported = async move {
55 let page = if let Some(page) = ctx.peer_extended_features(page_number) {
56 page
57 } else {
58 crate::lmp::procedure::features::initiate(ctx, page_number).await
59 };
60 page & feature_mask != 0
61 };
62 local_supported && peer_supported.await
63 }
64
supported_on_both_page1( ctx: &impl Context, feature: crate::packets::hci::LMPFeaturesPage1Bits, ) -> bool65 pub async fn supported_on_both_page1(
66 ctx: &impl Context,
67 feature: crate::packets::hci::LMPFeaturesPage1Bits,
68 ) -> bool {
69 supported_on_both_page(ctx, 1, feature.into()).await
70 }
71
supported_on_both_page2( ctx: &impl Context, feature: crate::packets::hci::LMPFeaturesPage2Bits, ) -> bool72 pub async fn supported_on_both_page2(
73 ctx: &impl Context,
74 feature: crate::packets::hci::LMPFeaturesPage2Bits,
75 ) -> bool {
76 supported_on_both_page(ctx, 2, feature.into()).await
77 }
78