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 use std::convert::TryFrom;
16 use std::future::Future;
17 use std::pin::Pin;
18 use std::task::{self, Poll};
19
20 use crate::lmp::ec::PrivateKey;
21 use crate::packets::{hci, lmp};
22
23 pub trait Context {
poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C>24 fn poll_hci_command<C: TryFrom<hci::Command>>(&self) -> Poll<C>;
poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P>25 fn poll_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> Poll<P>;
26
send_hci_event<E: Into<hci::Event>>(&self, event: E)27 fn send_hci_event<E: Into<hci::Event>>(&self, event: E);
send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P)28 fn send_lmp_packet<P: Into<lmp::LmpPacket>>(&self, packet: P);
29
peer_address(&self) -> hci::Address30 fn peer_address(&self) -> hci::Address;
peer_handle(&self) -> u1631 fn peer_handle(&self) -> u16;
32
peer_extended_features(&self, _features_page: u8) -> Option<u64>33 fn peer_extended_features(&self, _features_page: u8) -> Option<u64> {
34 None
35 }
36
extended_features(&self, features_page: u8) -> u6437 fn extended_features(&self, features_page: u8) -> u64;
38
receive_hci_command<C: TryFrom<hci::Command>>(&self) -> ReceiveFuture<'_, Self, C>39 fn receive_hci_command<C: TryFrom<hci::Command>>(&self) -> ReceiveFuture<'_, Self, C> {
40 ReceiveFuture(Self::poll_hci_command, self)
41 }
42
receive_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> ReceiveFuture<'_, Self, P>43 fn receive_lmp_packet<P: TryFrom<lmp::LmpPacket>>(&self) -> ReceiveFuture<'_, Self, P> {
44 ReceiveFuture(Self::poll_lmp_packet, self)
45 }
46
send_accepted_lmp_packet<P: Into<lmp::LmpPacket>>( &self, packet: P, ) -> SendAcceptedLmpPacketFuture<'_, Self>47 fn send_accepted_lmp_packet<P: Into<lmp::LmpPacket>>(
48 &self,
49 packet: P,
50 ) -> SendAcceptedLmpPacketFuture<'_, Self> {
51 let packet = packet.into();
52 let opcode = packet.get_opcode();
53 self.send_lmp_packet(packet);
54
55 SendAcceptedLmpPacketFuture(self, opcode)
56 }
57
58 #[allow(dead_code)]
get_private_key(&self) -> Option<PrivateKey>59 fn get_private_key(&self) -> Option<PrivateKey> {
60 None
61 }
62
set_private_key(&self, _key: &PrivateKey)63 fn set_private_key(&self, _key: &PrivateKey) {}
64 }
65
66 /// Future for Context::receive_hci_command and Context::receive_lmp_packet
67 pub struct ReceiveFuture<'a, C: ?Sized, P>(fn(&'a C) -> Poll<P>, &'a C);
68
69 impl<'a, C, O> Future for ReceiveFuture<'a, C, O>
70 where
71 C: Context,
72 {
73 type Output = O;
74
poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output>75 fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
76 (self.0)(self.1)
77 }
78 }
79
80 /// Future for Context::receive_hci_command and Context::receive_lmp_packet
81 pub struct SendAcceptedLmpPacketFuture<'a, C: ?Sized>(&'a C, lmp::Opcode);
82
83 impl<'a, C> Future for SendAcceptedLmpPacketFuture<'a, C>
84 where
85 C: Context,
86 {
87 type Output = Result<(), u8>;
88
poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output>89 fn poll(self: Pin<&mut Self>, _cx: &mut task::Context<'_>) -> Poll<Self::Output> {
90 let accepted = self.0.poll_lmp_packet::<lmp::Accepted>();
91 if let Poll::Ready(accepted) = accepted {
92 if accepted.get_accepted_opcode() == self.1 {
93 return Poll::Ready(Ok(()));
94 }
95 }
96
97 let not_accepted = self.0.poll_lmp_packet::<lmp::NotAccepted>();
98 if let Poll::Ready(not_accepted) = not_accepted {
99 if not_accepted.get_not_accepted_opcode() == self.1 {
100 return Poll::Ready(Err(not_accepted.get_error_code()));
101 }
102 }
103
104 Poll::Pending
105 }
106 }
107
108 pub mod authentication;
109 mod encryption;
110 pub mod features;
111 pub mod legacy_pairing;
112 pub mod secure_simple_pairing;
113
114 macro_rules! run_procedures {
115 ($(
116 $idx:tt { $procedure:expr }
117 )+) => {{
118 $(
119 let $idx = async { loop { $procedure.await; } };
120 crate::future::pin!($idx);
121 )+
122
123 use std::future::Future;
124 use std::pin::Pin;
125 use std::task::{Poll, Context};
126
127 #[allow(non_camel_case_types)]
128 struct Join<'a, $($idx),+> {
129 $($idx: Pin<&'a mut $idx>),+
130 }
131
132 #[allow(non_camel_case_types)]
133 impl<'a, $($idx: Future<Output = ()>),+> Future for Join<'a, $($idx),+> {
134 type Output = ();
135
136 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
137 $(assert!(self.$idx.as_mut().poll(cx).is_pending());)+
138 Poll::Pending
139 }
140 }
141
142 Join {
143 $($idx),+
144 }.await
145 }}
146 }
147
run(ctx: impl Context)148 pub async fn run(ctx: impl Context) {
149 run_procedures! {
150 a { authentication::initiate(&ctx) }
151 b { authentication::respond(&ctx) }
152 c { encryption::initiate(&ctx) }
153 d { encryption::respond(&ctx) }
154 e { features::respond(&ctx) }
155 }
156 }
157