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