1use core::task::Poll;
3
4use bt_hci::cmd::le::{
5 LeAddDeviceToFilterAcceptList, LeClearAdvSets, LeClearFilterAcceptList, LeReadNumberOfSupportedAdvSets,
6 LeSetAdvData, LeSetAdvEnable, LeSetAdvParams, LeSetAdvSetRandomAddr, LeSetExtAdvData, LeSetExtAdvEnable,
7 LeSetExtAdvParams, LeSetExtScanResponseData, LeSetScanResponseData,
8};
9use bt_hci::controller::{Controller, ControllerCmdSync};
10use bt_hci::param::{AddrKind, AdvChannelMap, AdvHandle, AdvKind, AdvSet, BdAddr, LeConnRole, Operation};
11use embassy_futures::select::{select, Either};
12
13use crate::advertise::{Advertisement, AdvertisementParameters, AdvertisementSet, RawAdvertisement};
14use crate::connection::Connection;
15use crate::host::BleHost;
16use crate::{bt_hci_duration, bt_hci_ext_duration, Address, BleHostError, Error, PacketPool};
17
18pub struct Peripheral<'d, C, P: PacketPool> {
20 host: &'d BleHost<'d, C, P>,
21}
22
23impl<'d, C: Controller, P: PacketPool> Peripheral<'d, C, P> {
24 pub(crate) fn new(host: &'d BleHost<'d, C, P>) -> Self {
25 Self { host }
26 }
27
28 pub async fn set_filter_accept_list(&mut self, filter_accept_list: &[Address]) -> Result<(), BleHostError<C::Error>>
33 where
34 C: ControllerCmdSync<LeClearFilterAcceptList> + ControllerCmdSync<LeAddDeviceToFilterAcceptList>,
35 {
36 let host = &self.host;
37 host.command(LeClearFilterAcceptList::new()).await?;
38 for entry in filter_accept_list {
39 host.command(LeAddDeviceToFilterAcceptList::new(entry.kind, entry.addr))
40 .await?;
41 }
42 Ok(())
43 }
44
45 pub async fn advertise<'k>(
47 &mut self,
48 params: &AdvertisementParameters,
49 data: Advertisement<'k>,
50 ) -> Result<Advertiser<'d, C, P>, BleHostError<C::Error>>
51 where
52 C: for<'t> ControllerCmdSync<LeSetAdvData>
53 + ControllerCmdSync<LeSetAdvParams>
54 + for<'t> ControllerCmdSync<LeSetAdvEnable>
55 + for<'t> ControllerCmdSync<LeSetScanResponseData>,
56 {
57 let host = &self.host;
58
59 if !data.is_valid() {
60 return Err(BleHostError::BleHost(Error::InvalidValue));
61 }
62
63 let drop = crate::host::OnDrop::new(|| {
65 host.advertise_command_state.cancel(false);
66 });
67 host.advertise_command_state.request().await;
68
69 host.advertise_state.reset();
71
72 let data: RawAdvertisement = data.into();
73 if !data.props.legacy_adv() {
74 return Err(Error::ExtendedAdvertisingNotSupported.into());
75 }
76
77 let kind = match (
78 data.props.connectable_adv(),
79 data.props.scannable_adv(),
80 data.props.high_duty_cycle_directed_connectable_adv(),
81 ) {
82 (true, true, _) => AdvKind::AdvInd,
83 (true, false, true) => AdvKind::AdvDirectIndHigh,
84 (true, false, false) => AdvKind::AdvDirectIndLow,
85 (false, true, _) => AdvKind::AdvScanInd,
86 (false, false, _) => AdvKind::AdvNonconnInd,
87 };
88 let peer = data.peer.unwrap_or(Address::new(AddrKind::PUBLIC, BdAddr::default()));
89
90 host.command(LeSetAdvParams::new(
91 bt_hci_duration(params.interval_min),
92 bt_hci_duration(params.interval_max),
93 kind,
94 params.own_addr_kind.unwrap_or_else(|| host.own_addr_kind()),
95 peer.kind,
96 peer.addr,
97 params.channel_map.unwrap_or(AdvChannelMap::ALL),
98 params.filter_policy,
99 ))
100 .await?;
101
102 if !data.adv_data.is_empty() {
103 let mut buf = [0; 31];
104 let to_copy = data.adv_data.len().min(buf.len());
105 buf[..to_copy].copy_from_slice(&data.adv_data[..to_copy]);
106 host.command(LeSetAdvData::new(to_copy as u8, buf)).await?;
107 }
108
109 if !data.scan_data.is_empty() {
110 let mut buf = [0; 31];
111 let to_copy = data.scan_data.len().min(buf.len());
112 buf[..to_copy].copy_from_slice(&data.scan_data[..to_copy]);
113 host.command(LeSetScanResponseData::new(to_copy as u8, buf)).await?;
114 }
115
116 let advset: [AdvSet; 1] = [AdvSet {
117 adv_handle: AdvHandle::new(0),
118 duration: bt_hci_duration(params.timeout.unwrap_or(embassy_time::Duration::from_micros(0))),
119 max_ext_adv_events: 0,
120 }];
121
122 trace!("[host] enabling advertising");
123 host.advertise_state.start(&advset[..]);
124 host.command(LeSetAdvEnable::new(true)).await?;
125 drop.defuse();
126 Ok(Advertiser {
127 host: self.host,
128 extended: false,
129 done: false,
130 })
131 }
132
133 pub async fn update_adv_data<'k>(&mut self, data: Advertisement<'k>) -> Result<(), BleHostError<C::Error>>
139 where
140 C: for<'t> ControllerCmdSync<LeSetAdvData> + for<'t> ControllerCmdSync<LeSetScanResponseData>,
141 {
142 let host = &self.host;
143
144 if !data.is_valid() {
145 return Err(BleHostError::BleHost(Error::InvalidValue));
146 }
147
148 let data: RawAdvertisement = data.into();
149 if !data.props.legacy_adv() {
150 return Err(Error::ExtendedAdvertisingNotSupported.into());
151 }
152 if !data.adv_data.is_empty() {
153 let mut buf = [0; 31];
154 let to_copy = data.adv_data.len().min(buf.len());
155 buf[..to_copy].copy_from_slice(&data.adv_data[..to_copy]);
156 host.command(LeSetAdvData::new(to_copy as u8, buf)).await?;
157 }
158 if !data.scan_data.is_empty() {
159 let mut buf = [0; 31];
160 let to_copy = data.scan_data.len().min(buf.len());
161 buf[..to_copy].copy_from_slice(&data.scan_data[..to_copy]);
162 host.command(LeSetScanResponseData::new(to_copy as u8, buf)).await?;
163 }
164 Ok(())
165 }
166
167 pub async fn advertise_ext<'k>(
177 &mut self,
178 sets: &[AdvertisementSet<'k>],
179 handles: &mut [AdvSet],
180 ) -> Result<Advertiser<'d, C, P>, BleHostError<C::Error>>
181 where
182 C: for<'t> ControllerCmdSync<LeSetExtAdvData<'t>>
183 + ControllerCmdSync<LeClearAdvSets>
184 + ControllerCmdSync<LeSetExtAdvParams>
185 + ControllerCmdSync<LeSetAdvSetRandomAddr>
186 + ControllerCmdSync<LeReadNumberOfSupportedAdvSets>
187 + for<'t> ControllerCmdSync<LeSetExtAdvEnable<'t>>
188 + for<'t> ControllerCmdSync<LeSetExtScanResponseData<'t>>,
189 {
190 assert_eq!(sets.len(), handles.len());
191 let host = &self.host;
192
193 for set in sets.iter() {
195 if !set.data.is_valid() {
196 return Err(BleHostError::BleHost(Error::InvalidValue));
197 }
198 }
199
200 {
202 let result = host.command(LeReadNumberOfSupportedAdvSets::new()).await?;
203 if result < sets.len() as u8 || host.advertise_state.len() < sets.len() {
204 return Err(Error::InsufficientSpace.into());
205 }
206 }
207
208 let drop = crate::host::OnDrop::new(|| {
210 host.advertise_command_state.cancel(true);
211 });
212 host.advertise_command_state.request().await;
213
214 host.advertise_state.reset();
216
217 for (i, set) in sets.iter().enumerate() {
218 let handle = AdvHandle::new(i as u8);
219 let data: RawAdvertisement<'k> = set.data.into();
220 let params = set.params;
221 let peer = data.peer.unwrap_or(Address::new(AddrKind::PUBLIC, BdAddr::default()));
222 let own_addr_kind = params.own_addr_kind.unwrap_or_else(|| host.own_addr_kind());
223 let random_addr = if let Some(addr) = set.address {
224 Some(addr)
225 } else {
226 host.address.as_ref().map(|a| a.addr)
227 };
228
229 host.command(LeSetExtAdvParams::new(
230 handle,
231 data.props,
232 bt_hci_ext_duration(params.interval_min),
233 bt_hci_ext_duration(params.interval_max),
234 params.channel_map.unwrap_or(AdvChannelMap::ALL),
235 own_addr_kind,
236 peer.kind,
237 peer.addr,
238 params.filter_policy,
239 params.tx_power as i8,
240 params.primary_phy,
241 0,
242 params.secondary_phy,
243 0,
244 false,
245 ))
246 .await?;
247
248 if let Some(addr) = random_addr {
249 host.command(LeSetAdvSetRandomAddr::new(handle, addr)).await?;
250 }
251
252 if !data.adv_data.is_empty() {
253 host.command(LeSetExtAdvData::new(
254 handle,
255 Operation::Complete,
256 params.fragment,
257 data.adv_data,
258 ))
259 .await?;
260 }
261
262 if !data.scan_data.is_empty() {
263 host.command(LeSetExtScanResponseData::new(
264 handle,
265 Operation::Complete,
266 params.fragment,
267 data.scan_data,
268 ))
269 .await?;
270 }
271 handles[i].adv_handle = handle;
272 handles[i].duration = bt_hci_duration(set.params.timeout.unwrap_or(embassy_time::Duration::from_micros(0)));
273 handles[i].max_ext_adv_events = set.params.max_events.unwrap_or(0);
274 }
275
276 trace!("[host] enabling extended advertising");
277 host.advertise_state.start(handles);
278 host.command(LeSetExtAdvEnable::new(true, handles)).await?;
279 drop.defuse();
280 Ok(Advertiser {
281 host: self.host,
282 extended: true,
283 done: false,
284 })
285 }
286
287 pub async fn update_adv_data_ext<'k>(
293 &mut self,
294 sets: &[AdvertisementSet<'k>],
295 handles: &mut [AdvSet],
296 ) -> Result<(), BleHostError<C::Error>>
297 where
298 C: for<'t> ControllerCmdSync<LeSetExtAdvData<'t>> + for<'t> ControllerCmdSync<LeSetExtScanResponseData<'t>>,
299 {
300 assert_eq!(sets.len(), handles.len());
301 let host = &self.host;
302 for (i, set) in sets.iter().enumerate() {
303 if !set.data.is_valid() {
304 return Err(BleHostError::BleHost(Error::InvalidValue));
305 }
306
307 let handle = handles[i].adv_handle;
308 let data: RawAdvertisement<'k> = set.data.into();
309 if !data.adv_data.is_empty() {
310 host.command(LeSetExtAdvData::new(
311 handle,
312 Operation::Complete,
313 set.params.fragment,
314 data.adv_data,
315 ))
316 .await?;
317 }
318 if !data.scan_data.is_empty() {
319 host.command(LeSetExtScanResponseData::new(
320 handle,
321 Operation::Complete,
322 set.params.fragment,
323 data.scan_data,
324 ))
325 .await?;
326 }
327 }
328 Ok(())
329 }
330
331 pub fn try_accept(&mut self) -> Option<Connection<'d, P>> {
335 if let Poll::Ready(conn) = self.host.connections.poll_accept(LeConnRole::Peripheral, &[], None) {
336 Some(conn)
337 } else {
338 None
339 }
340 }
341}
342
343pub struct Advertiser<'d, C, P: PacketPool> {
345 host: &'d BleHost<'d, C, P>,
346 extended: bool,
347 done: bool,
348}
349
350impl<'d, C: Controller, P: PacketPool> Advertiser<'d, C, P> {
351 pub async fn accept(mut self) -> Result<Connection<'d, P>, Error> {
355 let result = match select(
356 self.host.connections.accept(LeConnRole::Peripheral, &[]),
357 self.host.advertise_state.wait(),
358 )
359 .await
360 {
361 Either::First(conn) => Ok(conn),
362 Either::Second(_) => Err(Error::Timeout),
363 };
364 self.done = true;
365 result
366 }
367}
368
369impl<C, P: PacketPool> Drop for Advertiser<'_, C, P> {
370 fn drop(&mut self) {
371 if !self.done {
372 self.host.advertise_command_state.cancel(self.extended);
373 } else {
374 self.host.advertise_command_state.canceled();
375 }
376 }
377}