stm32wb_hci/vendor/command/gap.rs
1//! GAP commands and types needed for those commands.
2
3extern crate byteorder;
4
5pub use crate::host::{AdvertisingFilterPolicy, AdvertisingType, OwnAddressType};
6use crate::types::extended_advertisement::{
7 AdvSet, AdvertisingEvent, AdvertisingOperation, AdvertisingPhy, ExtendedAdvertisingInterval,
8};
9pub use crate::types::{ConnectionInterval, ExpectedConnectionLength, ScanWindow};
10use crate::{
11 host::{Channels, PeerAddrType, ScanFilterPolicy, ScanType},
12 types::extended_advertisement::AdvertisingMode,
13};
14use crate::{AdvertisingHandle, ConnectionHandle, Controller};
15pub use crate::{BdAddr, BdAddrType};
16use byteorder::{ByteOrder, LittleEndian};
17use core::time::Duration;
18
19/// GAP-specific commands.
20pub trait GapCommands {
21 /// Set the device in non-discoverable mode. This command will disable the LL advertising and
22 /// put the device in standby state.
23 ///
24 /// # Errors
25 ///
26 /// Only underlying communication errors are reported.
27 ///
28 /// # Generated events
29 ///
30 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetNonDiscoverable) event
31 /// is generated.
32 async fn gap_set_nondiscoverable(&mut self);
33
34 /// Set the device in limited discoverable mode.
35 ///
36 /// Limited discoverability is defined in in GAP specification volume 3, section 9.2.3. The
37 /// device will be discoverable for maximum period of TGAP (lim_adv_timeout) = 180 seconds (from
38 /// errata). The advertising can be disabled at any time by issuing a
39 /// [`set_nondiscoverable`](GapCommands::gap_set_nondiscoverable) command.
40 ///
41 /// # Errors
42 ///
43 /// - [`BadAdvertisingType`](Error::BadAdvertisingType) if
44 /// [`advertising_type`](DiscoverableParameters::advertising_type) is one of the disallowed
45 /// types:
46 /// [ConnectableDirectedHighDutyCycle](crate::host::AdvertisingType::ConnectableDirectedHighDutyCycle)
47 /// or
48 /// [ConnectableDirectedLowDutyCycle](crate::host::AdvertisingType::ConnectableDirectedLowDutyCycle).
49 /// - [`BadAdvertisingInterval`](Error::BadAdvertisingInterval) if
50 /// [`advertising_interval`](DiscoverableParameters::advertising_interval) is inverted.
51 /// That is, if the min is greater than the max.
52 /// - [`BadConnectionInterval`](Error::BadConnectionInterval) if
53 /// [`conn_interval`](DiscoverableParameters::conn_interval) is inverted. That is, both the
54 /// min and max are provided, and the min is greater than the max.
55 ///
56 /// # Generated evenst
57 ///
58 /// When the controller receives the command, it will generate a [command status](crate::event::Event::CommandStatus)
59 /// event. The controller starts the advertising after this and when advertising timeout happens
60 /// (i.e. limited discovery period has elapsed), the controller generates an
61 /// [GAP Limited Discoverable Complete](crate::vendor::event::VendorEvent::GapLimitedDiscoverableTimeout) event.
62
63 async fn set_limited_discoverable(
64 &mut self,
65 params: &DiscoverableParameters<'_, '_>,
66 ) -> Result<(), Error>;
67
68 /// Set the device in discoverable mode.
69 ///
70 /// Limited discoverability is defined in in GAP specification volume 3, section 9.2.4. The
71 /// device will be discoverable for maximum period of TGAP (lim_adv_timeout) = 180 seconds (from
72 /// errata). The advertising can be disabled at any time by issuing a
73 /// [`set_nondiscoverable`](GapCommands::set_nondiscoverable) command.
74 ///
75 /// # Errors
76 ///
77 /// - [`BadAdvertisingType`](Error::BadAdvertisingType) if
78 /// [`advertising_type`](DiscoverableParameters::advertising_type) is one of the disallowed
79 /// types:
80 /// [ConnectableDirectedHighDutyCycle](crate::host::AdvertisingType::ConnectableDirectedHighDutyCycle)
81 /// or
82 /// [ConnectableDirectedLowDutyCycle](crate::host::AdvertisingType::ConnectableDirectedLowDutyCycle).
83 /// - [`BadAdvertisingInterval`](Error::BadAdvertisingInterval) if
84 /// [`advertising_interval`](DiscoverableParameters::advertising_interval) is inverted.
85 /// That is, if the min is greater than the max.
86 /// - [`BadConnectionInterval`](Error::BadConnectionInterval) if
87 /// [`conn_interval`](DiscoverableParameters::conn_interval) is inverted. That is, both the
88 /// min and max are provided, and the min is greater than the max.
89 ///
90 /// # Generated evenst
91 ///
92 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetDiscoverable) event is
93 /// generated.
94 async fn set_discoverable(
95 &mut self,
96 params: &DiscoverableParameters<'_, '_>,
97 ) -> Result<(), Error>;
98
99 /// Set the device in direct connectable mode.
100 ///
101 /// Direct connectable mode is defined in GAP specification Volume 3,
102 /// Section 9.3.3). Device uses direct connectable mode to advertise using either High Duty
103 /// cycle advertisement events or Low Duty cycle advertisement events and the address as
104 /// what is specified in the Own Address Type parameter. The Advertising Type parameter in
105 /// the command specifies the type of the advertising used.
106 ///
107 /// When the `ms` feature is _not_ enabled, the device will be in directed connectable mode only
108 /// for 1.28 seconds. If no connection is established within this duration, the device enters
109 /// non discoverable mode and advertising will have to be again enabled explicitly.
110 ///
111 /// When the `ms` feature _is_ enabled, the advertising interval is explicitly provided in the
112 /// [parameters][DirectConnectableParameters].
113 ///
114 /// # Errors
115 ///
116 /// - [`BadAdvertisingType`](Error::BadAdvertisingType) if
117 /// [`advertising_type`](DiscoverableParameters::advertising_type) is one of the disallowed
118 /// types:
119 /// [ConnectableUndirected](crate::host::AdvertisingType::ConnectableUndirected),
120 /// [ScannableUndirected](crate::host::AdvertisingType::ScannableUndirected), or
121 /// [NonConnectableUndirected](crate::host::AdvertisingType::NonConnectableUndirected),
122 /// - (`ms` feature only) [`BadAdvertisingInterval`](Error::BadAdvertisingInterval) if
123 /// [`advertising_interval`](DiscoverableParameters::advertising_interval) is
124 /// out of range (20 ms to 10.24 s) or inverted (the min is greater than the max).
125 ///
126 /// # Generated evenst
127 ///
128 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetDirectConnectable) event
129 /// is generated.
130 async fn set_direct_connectable(
131 &mut self,
132 params: &DirectConnectableParameters,
133 ) -> Result<(), Error>;
134
135 /// Set the IO capabilities of the device.
136 ///
137 /// This command has to be given only when the device is not in a connected state.
138 ///
139 /// # Errors
140 ///
141 /// Only underlying communication errors are reported.
142 ///
143 /// # Generated events
144 ///
145 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetIoCapability) event is
146 /// generated.
147 async fn set_io_capability(&mut self, capability: IoCapability);
148
149 /// Set the authentication requirements for the device.
150 ///
151 /// This command has to be given only when the device is not in a connected state.
152 ///
153 /// # Errors
154 ///
155 /// - [BadEncryptionKeySizeRange](Error::BadEncryptionKeySizeRange) if the
156 /// [`encryption_key_size_range`](AuthenticationRequirements::encryption_key_size_range) min
157 /// is greater than the max.
158 /// - [BadFixedPin](Error::BadFixedPin) if the
159 /// [`fixed_pin`](AuthenticationRequirements::fixed_pin) is [Fixed](Pin::Fixed) with a value
160 /// greater than 999999.
161 /// - Underlying communication errors.
162 ///
163 /// # Generated events
164 ///
165 /// - A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetAuthenticationRequirement) event
166 /// is generated.
167 /// - If [`fixed_pin`](AuthenticationRequirements::fixed_pin) is [Request](Pin::Requested), then
168 /// a [GAP Pass Key](crate::vendor::event::VendorEvent::GapPassKeyRequest) event is generated.
169 async fn set_authentication_requirement(
170 &mut self,
171 requirements: &AuthenticationRequirements,
172 ) -> Result<(), Error>;
173
174 /// Set the authorization requirements of the device.
175 ///
176 /// This command has to be given when connected to a device if authorization is required to
177 /// access services which require authorization.
178 ///
179 /// # Errors
180 ///
181 /// Only underlying communication errors are reported.
182 ///
183 /// # Generated events
184 ///
185 /// - A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetAuthorizationRequirement) event
186 /// is generated.
187 /// - If authorization is required, then a [GAP Authorization Request](crate::vendor::event::VendorEvent::GapAuthorizationRequest)
188 /// event is generated.
189 async fn set_authorization_requirement(
190 &mut self,
191 conn_handle: crate::ConnectionHandle,
192 authorization_required: bool,
193 );
194
195 /// This command should be send by the host in response to the
196 /// [GAP Pass Key Request](crate::vendor::event::VendorEvent::GapPassKeyRequest) event.
197 ///
198 /// `pin` contains the pass key which will be used during the pairing process.
199 ///
200 /// # Errors
201 ///
202 /// - [BadFixedPin](Error::BadFixedPin) if the pin is greater than 999999.
203 /// - Underlying communication errors.
204 ///
205 /// # Generated events
206 ///
207 /// - A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapPassKeyResponse) event is
208 /// generated.
209 /// - When the pairing process completes, it will generate a
210 /// [PairingComplete](crate::vendor::event::VendorEvent::GapPairingComplete) event.
211 async fn pass_key_response(
212 &mut self,
213 conn_handle: crate::ConnectionHandle,
214 pin: u32,
215 ) -> Result<(), Error>;
216
217 /// This command should be send by the host in response to the
218 /// [GAP Authorization Request](crate::vendor::event::VendorEvent::GapAuthorizationRequest) event.
219 ///
220 /// # Errors
221 ///
222 /// Only underlying communication errors are reported.
223 ///
224 /// # Generated events
225 ///
226 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapAuthorizationResponse)
227 /// event is generated.
228 async fn authorization_response(
229 &mut self,
230 conn_handle: crate::ConnectionHandle,
231 authorization: Authorization,
232 );
233
234 /// Register the GAP service with the GATT.
235 ///
236 /// The device name characteristic and appearance characteristic are added by default and the
237 /// handles of these characteristics are returned in the
238 /// [event data](crate::vendor::event::command::GapInit).
239 ///
240 /// # Errors
241 ///
242 /// Only underlying communication errors are reported.
243 ///
244 /// # Generated events
245 ///
246 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapInit) event is generated.
247 async fn init(&mut self, role: Role, privacy_enabled: bool, dev_name_characteristic_len: u8);
248
249 /// Register the GAP service with the GATT.
250 ///
251 /// This function exists to prevent name conflicts with other Commands traits' init methods.
252 async fn init_gap(
253 &mut self,
254 role: Role,
255 privacy_enabled: bool,
256 dev_name_characteristic_len: u8,
257 ) {
258 self.init(role, privacy_enabled, dev_name_characteristic_len)
259 .await
260 }
261
262 /// Put the device into non-connectable mode.
263 ///
264 /// This mode does not support connection. The privacy setting done in the
265 /// [`init`](GapCommands::init) command plays a role in deciding the valid
266 /// parameters for this command. If privacy was not enabled, `address_type` may be
267 /// [Public](AddressType::Public) or [Random](AddressType::Random). If privacy was
268 /// enabled, `address_type` may be [ResolvablePrivate](AddressType::ResolvablePrivate) or
269 /// [NonResolvablePrivate](AddressType::NonResolvablePrivate).
270 ///
271 /// # Errors
272 ///
273 /// - [BadAdvertisingType](Error::BadAdvertisingType) if the advertising type is not one
274 /// of the supported modes. It must be
275 /// [ScannableUndirected](AdvertisingType::ScannableUndirected) or
276 /// [NonConnectableUndirected](AdvertisingType::NonConnectableUndirected).
277 /// - Underlying communication errors.
278 ///
279 /// # Generated events
280 ///
281 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapInit) event is generated.
282 async fn set_nonconnectable(
283 &mut self,
284 advertising_type: AdvertisingType,
285 address_type: AddressType,
286 ) -> Result<(), Error>;
287
288 /// Put the device into undirected connectable mode.
289 ///
290 /// The privacy setting done in the [`init`](GapCommands::init) command plays a role
291 /// in deciding the valid parameters for this command.
292 ///
293 /// # Errors
294 ///
295 /// - [BadAdvertisingFilterPolicy](Error::BadAdvertisingFilterPolicy) if the filter is
296 /// not one of the supported modes. It must be
297 /// [AllowConnectionAndScan](AdvertisingFilterPolicy::AllowConnectionAndScan) or
298 /// [WhiteListConnectionAllowScan](AdvertisingFilterPolicy::WhiteListConnectionAllowScan).
299 /// - Underlying communication errors.
300 ///
301 /// # Generated events
302 ///
303 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetUndirectedConnectable)
304 /// event is generated.
305 async fn set_undirected_connectable(
306 &mut self,
307 params: &UndirectedConnectableParameters,
308 ) -> Result<(), Error>;
309
310 /// This command has to be issued to notify the central device of the security requirements of
311 /// the peripheral.
312 ///
313 /// # Errors
314 ///
315 /// Only underlying communication errors are reported.
316 ///
317 /// # Generated events
318 ///
319 /// A [command status](crate::event::Event::CommandStatus) event will be generated when a valid
320 /// command is received. On completion of the command, i.e. when the security request is
321 /// successfully transmitted to the master, a
322 /// [GAP Peripheral Security Initiated](crate::vendor::event::VendorEvent::GapPeripheralSecurityInitiated)
323 /// vendor-specific event will be generated.
324 async fn peripheral_security_request(&mut self, conn_handle: &ConnectionHandle);
325
326 /// This command can be used to update the advertising data for a particular AD type. If the AD
327 /// type specified does not exist, then it is added to the advertising data. If the overall
328 /// advertising data length is more than 31 octets after the update, then the command is
329 /// rejected and the old data is retained.
330 ///
331 /// # Errors
332 ///
333 /// - [BadAdvertisingDataLength](Error::BadAdvertisingDataLength) if the provided data is longer
334 /// than 31 bytes.
335 /// - Underlying communication errors.
336 ///
337 /// # Generated events
338 ///
339 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapUpdateAdvertisingData)
340 /// event is generated.
341 async fn update_advertising_data(&mut self, data: &[u8]) -> Result<(), Error>;
342
343 /// This command can be used to delete the specified AD type from the advertisement data if
344 /// present.
345 ///
346 /// # Errors
347 ///
348 /// Only underlying communication errors are reported.
349 ///
350 /// # Generated events
351 ///
352 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapDeleteAdType) event is
353 /// generated.
354 async fn delete_ad_type(&mut self, ad_type: AdvertisingDataType);
355
356 /// This command can be used to get the current security settings of the device.
357 ///
358 /// # Errors
359 ///
360 /// Only underlying communication errors are reported.
361 ///
362 /// # Generated events
363 ///
364 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapGetSecurityLevel) event is
365 /// generated.
366 async fn get_security_level(&mut self, conn_handle: &ConnectionHandle);
367
368 /// Allows masking events from the GAP.
369 ///
370 /// The default configuration is all the events masked.
371 ///
372 /// # Errors
373 ///
374 /// Only underlying communication errors are reported.
375 ///
376 /// # Generated events
377 ///
378 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapSetEventMask) event is
379 /// generated.
380 async fn set_event_mask(&mut self, flags: EventFlags);
381
382 /// Allows masking events from the GAP.
383 ///
384 /// This function exists to prevent name conflicts with other Commands traits' set_event_mask
385 /// methods.
386 async fn set_gap_event_mask(&mut self, flags: EventFlags) {
387 self.set_event_mask(flags).await
388 }
389
390 /// Configure the controller's white list with devices that are present in the security
391 /// database.
392 ///
393 /// # Errors
394 ///
395 /// Only underlying communication errors are reported.
396 ///
397 /// # Generated events
398 ///
399 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapConfigureWhiteList) event
400 /// is generated.
401 async fn configure_white_list(&mut self);
402
403 /// Command the controller to terminate the connection.
404 ///
405 /// # Errors
406 ///
407 /// - [BadTerminationReason](Error::BadTerminationReason) if provided termination reason is
408 /// invalid. Valid reasons are the same as HCI [disconnect](crate::host::HostHci::disconnect):
409 /// [`AuthFailure`](crate::Status::AuthFailure),
410 /// [`RemoteTerminationByUser`](crate::Status::RemoteTerminationByUser),
411 /// [`RemoteTerminationLowResources`](crate::Status::RemoteTerminationLowResources),
412 /// [`RemoteTerminationPowerOff`](crate::Status::RemoteTerminationPowerOff),
413 /// [`UnsupportedRemoteFeature`](crate::Status::UnsupportedRemoteFeature),
414 /// [`PairingWithUnitKeyNotSupported`](crate::Status::PairingWithUnitKeyNotSupported), or
415 /// [`UnacceptableConnectionParameters`](crate::Status::UnacceptableConnectionParameters).
416 /// - Underlying communication errors.
417 ///
418 /// # Generated events
419 ///
420 /// The controller will generate a [command status](crate::event::Event::CommandStatus) event when
421 /// the command is received and a [Disconnection Complete](crate::event::Event::DisconnectionComplete)
422 /// event will be generated when the link is
423 /// disconnected.
424 async fn terminate(
425 &mut self,
426 conn_handle: crate::ConnectionHandle,
427 reason: crate::Status,
428 ) -> Result<(), Error>;
429
430 /// Clear the bonding table. All the devices in the bonding table are removed.
431 ///
432 /// See also [remove_bonded_device](GapCommands::remove_bonded_device) to remove only one device.
433 ///
434 /// # Note
435 /// As a fallback mode, in case the bonding table is full, the BLE stack automatically clears the bonding
436 /// table just before putting into it information about a new bonded device.
437 ///
438 /// # Errors
439 ///
440 /// Only underlying communication errors are reported.
441 ///
442 /// # Generated events
443 ///
444 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapClearSecurityDatabase)
445 /// event is generated.
446 async fn clear_security_database(&mut self);
447
448 /// This command should be given by the application when it receives the
449 /// [GAP Bond Lost](crate::vendor::event::VendorEvent::GapBondLost) event if it wants the re-bonding to happen
450 /// successfully. If this command is not given on receiving the event, the bonding procedure
451 /// will timeout.
452 ///
453 /// # Errors
454 ///
455 /// Only underlying communication errors are reported.
456 ///
457 /// # Generated events
458 ///
459 /// A [Command Complete](crate::vendor::event::command::VendorReturnParameters::GapAllowRebond) event is
460 /// generated. Even if the command is given when it is not valid, success will be returned but
461 /// internally it will have no effect.
462 async fn allow_rebond(&mut self, conn_handle: crate::ConnectionHandle);
463
464 /// Start the limited discovery procedure.
465 ///
466 /// The controller is commanded to start active scanning. When this procedure is started, only
467 /// the devices in limited discoverable mode are returned to the upper layers.
468 ///
469 /// # Errors
470 ///
471 /// Only underlying communication errors are reported.
472 ///
473 /// # Generated events
474 ///
475 /// A [command status](crate::event::Event::CommandStatus) event is generated as soon as the
476 /// command is given.
477 ///
478 /// If [Success](crate::Status::Success) is returned in the command status, the procedure is
479 /// terminated when either the upper layers issue a command to terminate the procedure by
480 /// issuing the command [`terminate_procedure`](GapCommands::terminate_gap_procedure) with the
481 /// procedure code set to [LimitedDiscovery](crate::vendor::event::GapProcedure::LimitedDiscovery) or a
482 /// [timeout](crate::vendor::event::VendorEvent::GapLimitedDiscoverableTimeout) happens. When the
483 /// procedure is terminated due to any of the above reasons, a
484 /// [ProcedureComplete](crate::vendor::event::VendorEvent::GapProcedureComplete) event is returned with
485 /// the procedure code set to [LimitedDiscovery](crate::vendor::event::GapProcedure::LimitedDiscovery).
486 ///
487 /// The device found when the procedure is ongoing is returned to the upper layers through the
488 /// [LeAdvertisingReport](crate::event::Event::LeAdvertisingReport) event.
489 async fn start_limited_discovery_procedure(&mut self, params: &DiscoveryProcedureParameters);
490
491 /// Start the general discovery procedure. The controller is commanded to start active scanning.
492 ///
493 /// # Errors
494 ///
495 /// Only underlying communication errors are reported.
496 ///
497 /// # Generated events
498 ///
499 /// A [command status](crate::event::Event::CommandStatus) event is generated as soon as the
500 /// command is given.
501 ///
502 /// If [Success](crate::Status::Success) is returned in the command status, the procedure is
503 /// terminated when either the upper layers issue a command to terminate the procedure by
504 /// issuing the command [`terminate_procedure`](GapCommands::terminate_gap_procedure) with the
505 /// procedure code set to [GeneralDiscovery](crate::vendor::event::GapProcedure::GeneralDiscovery) or a
506 /// timeout happens. When the procedure is terminated due to any of the above reasons, a
507 /// [ProcedureComplete](crate::vendor::event::VendorEvent::GapProcedureComplete) event is returned with
508 /// the procedure code set to [GeneralDiscovery](crate::vendor::event::GapProcedure::GeneralDiscovery).
509 ///
510 /// The device found when the procedure is ongoing is returned to the upper layers through the
511 /// [LeAdvertisingReport](crate::event::Event::LeAdvertisingReport) event.
512 async fn start_general_discovery_procedure(&mut self, params: &DiscoveryProcedureParameters);
513
514 /// Start the auto connection establishment procedure.
515 ///
516 /// The devices specified are added to the white list of the controller and a
517 /// [`le_create_connection`](crate::host::crate::le_create_connection) call will be made to the
518 /// controller by GAP with the [initiator filter policy](crate::host::ConnectionParameters::initiator_filter_policy) set to
519 /// [WhiteList](crate::host::ConnectionFilterPolicy::WhiteList), to "use whitelist to determine
520 /// which advertiser to connect to". When a command is issued to terminate the procedure by
521 /// upper layer, a [`le_create_connection_cancel`](crate::host::crate::le_create_connection_cancel)
522 /// call will be made to the controller by GAP.
523 ///
524 /// # Errors
525 ///
526 /// - If the [`white_list`](AutoConnectionEstablishmentParameters::white_list) is too long
527 /// (such that the serialized command would not fit in 255 bytes), a
528 /// [WhiteListTooLong](Error::WhiteListTooLong) is returned. The list cannot have more than 33
529 /// elements.
530 async fn start_auto_connection_establishment_procedure(
531 &mut self,
532 params: &AutoConnectionEstablishmentParameters<'_>,
533 ) -> Result<(), Error>;
534
535 /// Start a general connection establishment procedure.
536 ///
537 /// The host [enables scanning](crate::host::crate::le_set_scan_enable) in the controller with the
538 /// scanner [filter policy](crate::host::ScanParameters::filter_policy) set to
539 /// [AcceptAll](crate::host::ScanFilterPolicy::AcceptAll), to "accept all advertising packets" and
540 /// from the scanning results, all the devices are sent to the upper layer using the event
541 /// [LE Advertising Report](crate::event::Event::LeAdvertisingReport). The upper layer then has to
542 /// select one of the devices to which it wants to connect by issuing the command
543 /// [`create_connection`](GapCommands::create_connection). If privacy is enabled,
544 /// then either a private resolvable address or a non-resolvable address, based on the address
545 /// type specified in the command is set as the scanner address but the GAP create connection
546 /// always uses a private resolvable address if the general connection establishment procedure
547 /// is active.
548 ///
549 /// # Errors
550 ///
551 /// Only underlying communication errors are reported.
552 async fn start_general_connection_establishment_procedure(
553 &mut self,
554 params: &GeneralConnectionEstablishmentParameters,
555 );
556
557 /// Start a selective connection establishment procedure.
558 ///
559 /// The GAP adds the specified device addresses into white list and
560 /// [enables scanning](crate::host::HostHci::le_set_scan_enable) in the controller with the scanner
561 /// [filter policy](crate::host::ScanParameters::filter_policy) set to
562 /// [WhiteList](crate::host::ScanFilterPolicy::WhiteList), to "accept packets only from devices in
563 /// whitelist". All the devices found are sent to the upper layer by the event
564 /// [LE Advertising Report](crate::event::Event::LeAdvertisingReport). The upper layer then has to select one of
565 /// the devices to which it wants to connect by issuing the command
566 /// [`create_connection`](GapCommands::create_connection).
567 ///
568 /// # Errors
569 ///
570 /// - If the [`white_list`](SelectiveConnectionEstablishmentParameters::white_list) is too
571 /// long (such that the serialized command would not fit in 255 bytes), a
572 /// [WhiteListTooLong](Error::WhiteListTooLong) is returned. The list cannot have more than 35
573 /// elements.
574 async fn start_selective_connection_establishment_procedure(
575 &mut self,
576 params: &SelectiveConnectionEstablishmentParameters<'_>,
577 ) -> Result<(), Error>;
578
579 /// Start the direct connection establishment procedure.
580 ///
581 /// A [LE Create Connection](crate::host::crate::le_create_connection) call will be made to the
582 /// controller by GAP with the initiator [filter policy](crate::host::ConnectionParameters::initiator_filter_policy) set to
583 /// [UseAddress](crate::host::ConnectionFilterPolicy::UseAddress) to "ignore whitelist and process
584 /// connectable advertising packets only for the specified device". The procedure can be
585 /// terminated explicitly by the upper layer by issuing the command
586 /// [`terminate_procedure`](GapCommands::terminate_gap_procedure). When a command is
587 /// issued to terminate the procedure by upper layer, a
588 /// [`le_create_connection_cancel`](crate::host::HostHci::le_create_connection_cancel) call will be
589 /// made to the controller by GAP.
590 ///
591 /// # Errors
592 ///
593 /// Only underlying communication errors are reported.
594 ///
595 /// # Generated events
596 ///
597 /// A [command status](crate::event::Event::CommandStatus) event is generated as soon as the
598 /// command is given. If [Success](crate::Status::Success) is returned, on termination of the
599 /// procedure, a [LE Connection Complete](crate::event::LeConnectionComplete) event is
600 /// returned. The procedure can be explicitly terminated by the upper layer by issuing the
601 /// command [`terminate_procedure`](GapCommands::terminate_gap_procedure) with the procedure_code set
602 /// to
603 /// [DirectConnectionEstablishment](crate::vendor::event::GapProcedure::DirectConnectionEstablishment).
604 async fn create_connection(&mut self, params: &ConnectionParameters);
605
606 /// The GAP procedure(s) specified is terminated.
607 ///
608 /// # Errors
609 ///
610 /// - [NoProcedure](Error::NoProcedure) if the bitfield is empty.
611 /// - Underlying communication errors
612 ///
613 /// # Generated events
614 ///
615 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapTerminateProcedure) event
616 /// is generated for this command. If the command was successfully processed, the status field
617 /// will be [Success](crate::Status::Success) and a
618 /// [ProcedureCompleted](crate::vendor::event::VendorEvent::GapProcedureComplete) event is returned
619 /// with the procedure code set to the corresponding procedure.
620 async fn terminate_gap_procedure(&mut self, procedure: Procedure) -> Result<(), Error>;
621
622 /// Start the connection update procedure.
623 ///
624 /// A [`le_connection_update`](crate::host::HostHci::le_connection_update) call is be made to the
625 /// controller by GAP.
626 ///
627 /// # Errors
628 ///
629 /// Only underlying communication errors are reported.
630 ///
631 /// # Generated events
632 ///
633 /// A [command status](crate::event::Event::CommandStatus) event is generated as soon as the
634 /// command is given. If [Success](crate::Status::Success) is returned, on completion of
635 /// connection update, a
636 /// [LeConnectionUpdateComplete](crate::event::Event::LeConnectionUpdateComplete) event is
637 /// returned to the upper layer.
638 async fn start_connection_update(&mut self, params: &ConnectionUpdateParameters);
639
640 /// Send the SM pairing request to start a pairing process. The authentication requirements and
641 /// I/O capabilities should be set before issuing this command using the
642 /// [`set_io_capability`](GapCommands::set_io_capability) and
643 /// [`set_authentication_requirement`](GapCommands::set_authentication_requirement)
644 /// commands.
645 ///
646 /// # Errors
647 ///
648 /// Only underlying communication errors are reported.
649 ///
650 /// # Generated events
651 ///
652 /// A [command status](crate::event::Event::CommandStatus) event is generated when the command is
653 /// received. If [Success](crate::Status::Success) is returned in the command status event, a
654 /// [Pairing Complete](crate::vendor::event::VendorEvent::GapPairingComplete) event is returned after
655 /// the pairing process is completed.
656 async fn send_pairing_request(&mut self, params: &PairingRequest);
657
658 /// This command tries to resolve the address provided with the IRKs present in its database.
659 ///
660 /// If the address is resolved successfully with any one of the IRKs present in the database, it
661 /// returns success and also the corresponding public/static random address stored with the IRK
662 /// in the database.
663 ///
664 /// # Errors
665 ///
666 /// Only underlying communication errors are reported.
667 ///
668 /// # Generated events
669 ///
670 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapResolvePrivateAddress)
671 /// event is generated. If [Success](crate::Status::Success) is returned as the status, then the
672 /// address is also returned in the event.
673 async fn resolve_private_address(&mut self, addr: crate::BdAddr);
674
675 /// This command puts the device into broadcast mode.
676 ///
677 /// # Errors
678 ///
679 /// - [BadAdvertisingType](Error::BadAdvertisingType) if the advertising type is not
680 /// [ScannableUndirected](crate::types::AdvertisingType::ScannableUndirected) or
681 /// [NonConnectableUndirected](crate::types::AdvertisingType::NonConnectableUndirected).
682 /// - [BadAdvertisingDataLength](Error::BadAdvertisingDataLength) if the advertising data is
683 /// longer than 31 bytes.
684 /// - [WhiteListTooLong](Error::WhiteListTooLong) if the length of the white list would put the
685 /// packet length over 255 bytes. The exact number of addresses that can be in the white list
686 /// can range from 35 to 31, depending on the length of the advertising data.
687 /// - Underlying communication errors.
688 ///
689 /// # Generated events
690 ///
691 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapSetBroadcastMode) event is
692 /// returned where the status indicates whether the command was successful.
693 async fn set_broadcast_mode(&mut self, params: &BroadcastModeParameters) -> Result<(), Error>;
694
695 /// Starts an Observation procedure, when the device is in Observer Role.
696 ///
697 /// The host enables scanning in the controller. The advertising reports are sent to the upper
698 /// layer using standard LE Advertising Report Event. See Bluetooth Core v4.1, Vol. 2, part E,
699 /// Ch. 7.7.65.2, LE Advertising Report Event.
700 ///
701 /// # Errors
702 ///
703 /// Only underlying communication errors are reported.
704 ///
705 /// # Generated events
706 ///
707 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapStartObservationProcedure)
708 /// event is generated.
709 async fn start_observation_procedure(&mut self, params: &ObservationProcedureParameters);
710
711 /// This command gets the list of the devices which are bonded. It returns the number of
712 /// addresses and the corresponding address types and values.
713 ///
714 /// # Errors
715 ///
716 /// Only underlying communication errors are reported.
717 ///
718 /// # Generated events
719 ///
720 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapGetBondedDevices) event is
721 /// generated.
722 async fn get_bonded_devices(&mut self);
723
724 /// The command finds whether the device, whose address is specified in the command, is
725 /// bonded. If the device is using a resolvable private address and it has been bonded, then the
726 /// command will return [Success](crate::Status::Success).
727 ///
728 /// # Errors
729 ///
730 /// Only underlying communication errors are reported.
731 ///
732 /// # Generated events
733 ///
734 /// A [command complete](crate::vendor::event::command::VendorReturnParameters::GapIsDeviceBonded) event is
735 /// generated.
736 async fn is_device_bonded(&mut self, addr: crate::host::PeerAddrType);
737
738 /// This command allows the user to validate/confirm or not the numeric comparison value showed through
739 /// the [`NumericComparisonValueEvent`]
740 async fn numeric_comparison_value_confirm_yes_no(
741 &mut self,
742 params: &NumericComparisonValueConfirmYesNoParameters,
743 );
744
745 /// This command permits to signal to the Stack the input type detected during Passkey input.
746 async fn passkey_input(&mut self, conn_handle: ConnectionHandle, input_type: InputType);
747
748 /// This command is sent by the user to get (i.e. to extract from the Stack) the OOB
749 /// data generated by the Stack itself.
750 async fn get_oob_data(&mut self, oob_data_type: OobDataType);
751
752 /// This command is sent (by the User) to input the OOB data arrived via OOB
753 /// communication.
754 async fn set_oob_data(&mut self, params: &SetOobDataParameters);
755
756 /// This command is used to add devices to the list of address translations
757 /// used to resolve Resolvable Private Addresses in the Controller.
758 async fn add_devices_to_resolving_list(
759 &mut self,
760 whitelist_identities: &[PeerAddrType],
761 clear_resolving_list: bool,
762 );
763
764 /// This command is used to remove a specified device from bonding table
765 async fn remove_bonded_device(&mut self, address: BdAddrType);
766
767 /// This command is used to add specific device addresses to the white and/or resolving list.
768 async fn add_devices_to_list(&mut self, list_entries: &[BdAddrType], mode: AddDeviceToListMode);
769
770 /// This command starts an advertising beacon. It allows additional advertising
771 /// packets to be transmitted independently of the packets transmitted with GAP
772 /// advertising commands such as ACI_GAP_SET_DISCOVERABLE or
773 /// ACI_GAP_SET_LIMITED_DISCOVERABLE.
774 async fn additional_beacon_start(
775 &mut self,
776 params: &AdditonalBeaconStartParameters,
777 ) -> Result<(), Error>;
778
779 /// This command stops the advertising beacon started with
780 /// ACI_GAP_ADDITIONAL_BEACON_START.
781 async fn additional_beacon_stop(&mut self);
782
783 /// This command sets the data transmitted by the advertising beacon started
784 /// with ACI_GAP_ADDITIONAL_BEACON_START. If the advertising beacon is already
785 /// started, the new data is used in subsequent beacon advertising events.
786 async fn additonal_beacon_set_data(&mut self, advertising_data: &[u8]);
787
788 /// This command is used to set the extended advertising configuration for one
789 /// advertising set.
790 ///
791 /// This command, in association with
792 /// [adv_set_scan_response_data](GapCommands::adv_set_scan_response_data),
793 /// [adv_set_advertising_data](GapCommands::adv_set_advertising_data) and
794 /// [adv_set_enable](GapCommands::adv_set_enable), enables to start extended
795 /// advertising.
796 ///
797 /// These commands must be used in replacement of
798 /// [set_discoverable](GapCommands::set_discoverable),
799 /// [set_limited_discoverable](GapCommands::set_limited_discoverable),
800 /// [set_direct_connectable](GapCommands::set_direct_connectable),
801 /// [set_nonconnectable](GapCommands::set_nonconnectable),
802 /// [set_undirected_connectable](GapCommands::set_undirected_connectable) and
803 /// [set_broadcast_mode](GapCommands::set_broadcast_mode) that only support
804 /// legacy advertising.
805 async fn adv_set_config(&mut self, params: &AdvSetConfig);
806
807 /// This command is used to request the Controller to enable or disbale one
808 /// or more extended advertising sets.
809 async fn adv_set_enable<'a>(&mut self, params: &AdvSetEnable<'a>);
810
811 /// This command is used to set the data used in extended advertising PDUs
812 /// that have a data field
813 async fn adv_set_advertising_data(&mut self, params: &AdvSetAdvertisingData);
814
815 /// This command is used to provide scan response data used during extended
816 /// advertising
817 async fn adv_set_scan_response_data(&mut self, params: &AdvSetAdvertisingData);
818
819 /// This command is used to remove an advertising set from the Controller.
820 async fn adv_remove_set(&mut self, handle: AdvertisingHandle);
821
822 /// This command is used to remove all exisiting advertising sets from
823 /// the Controller.
824 async fn adv_clear_sets(&mut self);
825
826 /// This command is used to set the random device address of an advertising
827 /// set configured to use specific random address.
828 async fn adv_set_random_address(&mut self, handle: AdvertisingHandle, addr: BdAddr);
829}
830
831impl<T: Controller> GapCommands for T {
832 async fn gap_set_nondiscoverable(&mut self) {
833 self.controller_write(crate::vendor::opcode::GAP_SET_NONDISCOVERABLE, &[])
834 .await
835 }
836
837 impl_validate_variable_length_params!(
838 set_limited_discoverable<'a, 'b>,
839 DiscoverableParameters<'a, 'b>,
840 crate::vendor::opcode::GAP_SET_LIMITED_DISCOVERABLE
841 );
842
843 impl_validate_variable_length_params!(
844 set_discoverable<'a, 'b>,
845 DiscoverableParameters<'a, 'b>,
846 crate::vendor::opcode::GAP_SET_DISCOVERABLE
847 );
848
849 impl_validate_params!(
850 set_direct_connectable,
851 DirectConnectableParameters,
852 crate::vendor::opcode::GAP_SET_DIRECT_CONNECTABLE
853 );
854
855 async fn set_io_capability(&mut self, capability: IoCapability) {
856 self.controller_write(
857 crate::vendor::opcode::GAP_SET_IO_CAPABILITY,
858 &[capability as u8],
859 )
860 .await
861 }
862
863 impl_validate_params!(
864 set_authentication_requirement,
865 AuthenticationRequirements,
866 crate::vendor::opcode::GAP_SET_AUTHENTICATION_REQUIREMENT
867 );
868
869 async fn set_authorization_requirement(
870 &mut self,
871 conn_handle: crate::ConnectionHandle,
872 authorization_required: bool,
873 ) {
874 let mut bytes = [0; 3];
875 LittleEndian::write_u16(&mut bytes[0..2], conn_handle.0);
876 bytes[2] = authorization_required as u8;
877
878 self.controller_write(
879 crate::vendor::opcode::GAP_SET_AUTHORIZATION_REQUIREMENT,
880 &bytes,
881 )
882 .await
883 }
884
885 async fn pass_key_response(
886 &mut self,
887 conn_handle: crate::ConnectionHandle,
888 pin: u32,
889 ) -> Result<(), Error> {
890 if pin > 999_999 {
891 return Err(Error::BadFixedPin(pin));
892 }
893
894 let mut bytes = [0; 6];
895 LittleEndian::write_u16(&mut bytes[0..2], conn_handle.0);
896 LittleEndian::write_u32(&mut bytes[2..6], pin);
897
898 self.controller_write(crate::vendor::opcode::GAP_PASS_KEY_RESPONSE, &bytes)
899 .await;
900
901 Ok(())
902 }
903
904 async fn authorization_response(
905 &mut self,
906 conn_handle: crate::ConnectionHandle,
907 authorization: Authorization,
908 ) {
909 let mut bytes = [0; 3];
910 LittleEndian::write_u16(&mut bytes[0..2], conn_handle.0);
911 bytes[2] = authorization as u8;
912
913 self.controller_write(crate::vendor::opcode::GAP_AUTHORIZATION_RESPONSE, &bytes)
914 .await
915 }
916
917 async fn init(&mut self, role: Role, privacy_enabled: bool, dev_name_characteristic_len: u8) {
918 let mut bytes = [0; 3];
919 bytes[0] = role.bits();
920 bytes[1] = privacy_enabled as u8;
921 bytes[2] = dev_name_characteristic_len;
922
923 self.controller_write(crate::vendor::opcode::GAP_INIT, &bytes)
924 .await;
925 }
926
927 async fn set_nonconnectable(
928 &mut self,
929 advertising_type: AdvertisingType,
930 address_type: AddressType,
931 ) -> Result<(), Error> {
932 match advertising_type {
933 AdvertisingType::ScannableUndirected | AdvertisingType::NonConnectableUndirected => (),
934 _ => {
935 return Err(Error::BadAdvertisingType(advertising_type));
936 }
937 }
938
939 self.controller_write(
940 crate::vendor::opcode::GAP_SET_NONCONNECTABLE,
941 &[advertising_type as u8, address_type as u8],
942 )
943 .await;
944
945 Ok(())
946 }
947
948 impl_validate_params!(
949 set_undirected_connectable,
950 UndirectedConnectableParameters,
951 crate::vendor::opcode::GAP_SET_UNDIRECTED_CONNECTABLE
952 );
953
954 async fn peripheral_security_request(&mut self, conn_handle: &ConnectionHandle) {
955 let mut bytes = [0; 2];
956
957 LittleEndian::write_u16(&mut bytes[0..2], conn_handle.0);
958
959 self.controller_write(
960 crate::vendor::opcode::GAP_PERIPHERAL_SECURITY_REQUEST,
961 &bytes,
962 )
963 .await
964 }
965
966 async fn update_advertising_data(&mut self, data: &[u8]) -> Result<(), Error> {
967 const MAX_LENGTH: usize = 31;
968 if data.len() > MAX_LENGTH {
969 return Err(Error::BadAdvertisingDataLength(data.len()));
970 }
971
972 let mut bytes = [0; 1 + MAX_LENGTH];
973 bytes[0] = data.len() as u8;
974 bytes[1..=data.len()].copy_from_slice(data);
975
976 self.controller_write(
977 crate::vendor::opcode::GAP_UPDATE_ADVERTISING_DATA,
978 &bytes[0..=data.len()],
979 )
980 .await;
981
982 Ok(())
983 }
984
985 async fn delete_ad_type(&mut self, ad_type: AdvertisingDataType) {
986 self.controller_write(crate::vendor::opcode::GAP_DELETE_AD_TYPE, &[ad_type as u8])
987 .await
988 }
989
990 async fn get_security_level(&mut self, conn_handle: &ConnectionHandle) {
991 let mut bytes = [0; 2];
992
993 LittleEndian::write_u16(&mut bytes, conn_handle.0);
994
995 self.controller_write(crate::vendor::opcode::GAP_GET_SECURITY_LEVEL, &bytes)
996 .await
997 }
998
999 async fn set_event_mask(&mut self, flags: EventFlags) {
1000 let mut bytes = [0; 2];
1001 LittleEndian::write_u16(&mut bytes, flags.bits());
1002
1003 self.controller_write(crate::vendor::opcode::GAP_SET_EVENT_MASK, &bytes)
1004 .await
1005 }
1006
1007 async fn configure_white_list(&mut self) {
1008 self.controller_write(crate::vendor::opcode::GAP_CONFIGURE_WHITE_LIST, &[])
1009 .await
1010 }
1011
1012 async fn terminate(
1013 &mut self,
1014 conn_handle: crate::ConnectionHandle,
1015 reason: crate::Status,
1016 ) -> Result<(), Error> {
1017 match reason {
1018 crate::Status::AuthFailure
1019 | crate::Status::RemoteTerminationByUser
1020 | crate::Status::RemoteTerminationLowResources
1021 | crate::Status::RemoteTerminationPowerOff
1022 | crate::Status::UnsupportedRemoteFeature
1023 | crate::Status::PairingWithUnitKeyNotSupported
1024 | crate::Status::UnacceptableConnectionParameters => (),
1025 _ => return Err(Error::BadTerminationReason(reason)),
1026 }
1027
1028 let mut bytes = [0; 3];
1029 LittleEndian::write_u16(&mut bytes[0..2], conn_handle.0);
1030 bytes[2] = reason.into();
1031
1032 self.controller_write(crate::vendor::opcode::GAP_TERMINATE, &bytes)
1033 .await;
1034 Ok(())
1035 }
1036
1037 async fn clear_security_database(&mut self) {
1038 self.controller_write(crate::vendor::opcode::GAP_CLEAR_SECURITY_DATABASE, &[])
1039 .await
1040 }
1041
1042 async fn allow_rebond(&mut self, conn_handle: crate::ConnectionHandle) {
1043 let mut bytes = [0; 2];
1044 LittleEndian::write_u16(&mut bytes, conn_handle.0);
1045 self.controller_write(crate::vendor::opcode::GAP_ALLOW_REBOND, &bytes)
1046 .await
1047 }
1048
1049 impl_params!(
1050 start_limited_discovery_procedure,
1051 DiscoveryProcedureParameters,
1052 crate::vendor::opcode::GAP_START_LIMITED_DISCOVERY_PROCEDURE
1053 );
1054
1055 impl_params!(
1056 start_general_discovery_procedure,
1057 DiscoveryProcedureParameters,
1058 crate::vendor::opcode::GAP_START_GENERAL_DISCOVERY_PROCEDURE
1059 );
1060
1061 impl_validate_variable_length_params!(
1062 start_auto_connection_establishment_procedure<'a>,
1063 AutoConnectionEstablishmentParameters<'a>,
1064 crate::vendor::opcode::GAP_START_AUTO_CONNECTION_ESTABLISHMENT
1065 );
1066
1067 impl_params!(
1068 start_general_connection_establishment_procedure,
1069 GeneralConnectionEstablishmentParameters,
1070 crate::vendor::opcode::GAP_START_GENERAL_CONNECTION_ESTABLISHMENT
1071 );
1072
1073 impl_validate_variable_length_params!(
1074 start_selective_connection_establishment_procedure<'a>,
1075 SelectiveConnectionEstablishmentParameters<'a>,
1076 crate::vendor::opcode::GAP_START_SELECTIVE_CONNECTION_ESTABLISHMENT
1077 );
1078 impl_params!(
1079 create_connection,
1080 ConnectionParameters,
1081 crate::vendor::opcode::GAP_CREATE_CONNECTION
1082 );
1083
1084 async fn terminate_gap_procedure(&mut self, procedure: Procedure) -> Result<(), Error> {
1085 if procedure.is_empty() {
1086 return Err(Error::NoProcedure);
1087 }
1088
1089 self.controller_write(
1090 crate::vendor::opcode::GAP_TERMINATE_PROCEDURE,
1091 &[procedure.bits()],
1092 )
1093 .await;
1094
1095 Ok(())
1096 }
1097
1098 impl_params!(
1099 start_connection_update,
1100 ConnectionUpdateParameters,
1101 crate::vendor::opcode::GAP_START_CONNECTION_UPDATE
1102 );
1103
1104 impl_params!(
1105 send_pairing_request,
1106 PairingRequest,
1107 crate::vendor::opcode::GAP_SEND_PAIRING_REQUEST
1108 );
1109
1110 async fn resolve_private_address(&mut self, addr: crate::BdAddr) {
1111 self.controller_write(crate::vendor::opcode::GAP_RESOLVE_PRIVATE_ADDRESS, &addr.0)
1112 .await
1113 }
1114
1115 impl_validate_variable_length_params!(
1116 set_broadcast_mode<'a, 'b>,
1117 BroadcastModeParameters<'a, 'b>,
1118 crate::vendor::opcode::GAP_SET_BROADCAST_MODE
1119 );
1120
1121 impl_params!(
1122 start_observation_procedure,
1123 ObservationProcedureParameters,
1124 crate::vendor::opcode::GAP_START_OBSERVATION_PROCEDURE
1125 );
1126
1127 async fn get_bonded_devices(&mut self) {
1128 self.controller_write(crate::vendor::opcode::GAP_GET_BONDED_DEVICES, &[])
1129 .await
1130 }
1131
1132 async fn is_device_bonded(&mut self, addr: crate::host::PeerAddrType) {
1133 let mut bytes = [0; 7];
1134 addr.copy_into_slice(&mut bytes);
1135
1136 self.controller_write(crate::vendor::opcode::GAP_IS_DEVICE_BONDED, &bytes)
1137 .await
1138 }
1139
1140 impl_params!(
1141 numeric_comparison_value_confirm_yes_no,
1142 NumericComparisonValueConfirmYesNoParameters,
1143 crate::vendor::opcode::GAP_NUMERIC_COMPARISON_VALUE_YES_NO
1144 );
1145
1146 async fn passkey_input(&mut self, conn_handle: ConnectionHandle, input_type: InputType) {
1147 let mut bytes = [0; 3];
1148
1149 LittleEndian::write_u16(&mut bytes[..2], conn_handle.0);
1150 bytes[2] = input_type as u8;
1151
1152 self.controller_write(crate::vendor::opcode::GAP_PASSKEY_INPUT, &bytes)
1153 .await
1154 }
1155
1156 async fn get_oob_data(&mut self, oob_data_type: OobDataType) {
1157 self.controller_write(
1158 crate::vendor::opcode::GAP_GET_OOB_DATA,
1159 &[oob_data_type as u8],
1160 )
1161 .await
1162 }
1163
1164 impl_params!(
1165 set_oob_data,
1166 SetOobDataParameters,
1167 crate::vendor::opcode::GAP_SET_OOB_DATA
1168 );
1169
1170 async fn add_devices_to_resolving_list(
1171 &mut self,
1172 whitelist_identities: &[PeerAddrType],
1173 clear_resolving_list: bool,
1174 ) {
1175 let mut bytes = [0; 254];
1176
1177 bytes[0] = whitelist_identities.len() as u8;
1178
1179 let mut index = 1;
1180 for id in whitelist_identities {
1181 id.copy_into_slice(&mut bytes[index..index + 7]);
1182 index += 7;
1183 }
1184 bytes[index] = clear_resolving_list as u8;
1185
1186 self.controller_write(
1187 crate::vendor::opcode::GAP_ADD_DEVICES_TO_RESOLVING_LIST,
1188 &bytes[..(index + 1)],
1189 )
1190 .await;
1191 }
1192
1193 async fn remove_bonded_device(&mut self, address: BdAddrType) {
1194 let mut bytes = [0; 7];
1195
1196 address.copy_into_slice(&mut bytes);
1197 self.controller_write(crate::vendor::opcode::GAP_REMOVE_BONDED_DEVICE, &bytes)
1198 .await;
1199 }
1200
1201 async fn add_devices_to_list(
1202 &mut self,
1203 list_entries: &[BdAddrType],
1204 mode: AddDeviceToListMode,
1205 ) {
1206 let mut bytes = [0; 254];
1207
1208 bytes[0] = list_entries.len() as u8;
1209
1210 let mut index = 0;
1211 for entry in list_entries {
1212 entry.copy_into_slice(&mut bytes[index..index + 7]);
1213 index += 7;
1214 }
1215 bytes[index] = mode as u8;
1216
1217 self.controller_write(
1218 crate::vendor::opcode::GAP_ADD_DEVICES_TO_LIST,
1219 &bytes[..(index + 1)],
1220 )
1221 .await;
1222 }
1223
1224 impl_validate_params!(
1225 additional_beacon_start,
1226 AdditonalBeaconStartParameters,
1227 crate::vendor::opcode::GAP_ADDITIONAL_BEACON_START
1228 );
1229
1230 async fn additional_beacon_stop(&mut self) {
1231 self.controller_write(crate::vendor::opcode::GAP_ADDITIONAL_BEACON_STOP, &[])
1232 .await;
1233 }
1234
1235 async fn additonal_beacon_set_data(&mut self, advertising_data: &[u8]) {
1236 self.controller_write(
1237 crate::vendor::opcode::GAP_ADDITIONAL_BEACON_SET_DATA,
1238 advertising_data,
1239 )
1240 .await;
1241 }
1242
1243 impl_params!(
1244 adv_set_config,
1245 AdvSetConfig,
1246 crate::vendor::opcode::GAP_ADV_SET_CONFIGURATION
1247 );
1248
1249 impl_variable_length_params!(
1250 adv_set_enable<'a>,
1251 AdvSetEnable<'a>,
1252 crate::vendor::opcode::GAP_ADV_SET_ENABLE
1253 );
1254
1255 impl_variable_length_params!(
1256 adv_set_advertising_data<'a>,
1257 AdvSetAdvertisingData<'a>,
1258 crate::vendor::opcode::GAP_ADV_SET_ADV_DATA
1259 );
1260
1261 impl_variable_length_params!(
1262 adv_set_scan_response_data<'a>,
1263 AdvSetAdvertisingData<'a>,
1264 crate::vendor::opcode::GAP_ADV_SET_SCAN_RESPONSE_DATA
1265 );
1266
1267 async fn adv_remove_set(&mut self, handle: AdvertisingHandle) {
1268 self.controller_write(crate::vendor::opcode::GAP_ADV_REMOVE_SET, &[handle.0])
1269 .await;
1270 }
1271
1272 async fn adv_clear_sets(&mut self) {
1273 self.controller_write(crate::vendor::opcode::GAP_ADV_CLEAR_SETS, &[])
1274 .await;
1275 }
1276
1277 async fn adv_set_random_address(&mut self, handle: AdvertisingHandle, addr: BdAddr) {
1278 let mut payload = [0; 7];
1279 payload[0] = handle.0;
1280 payload[1..].copy_from_slice(&addr.0);
1281 self.controller_write(crate::vendor::opcode::GAP_ADV_SET_RANDOM_ADDRESS, &payload)
1282 .await;
1283 }
1284}
1285
1286/// Potential errors from parameter validation.
1287///
1288/// Before some commands are sent to the controller, the parameters are validated. This type
1289/// enumerates the potential validation errors. Must be specialized on the types of communication
1290/// errors.
1291#[derive(Copy, Clone, Debug, PartialEq)]
1292#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1293pub enum Error {
1294 /// For the [GAP Set Limited Discoverable](GapCommands::set_limited_discoverable) and
1295 /// [GAP Set Discoverable](GapCommands::set_discoverable) commands, the connection
1296 /// interval is inverted (the min is greater than the max). Return the provided min as the
1297 /// first element, max as the second.
1298 BadConnectionInterval(Duration, Duration),
1299
1300 /// For the [GAP Set Limited Discoverable](GapCommands::set_limited_discoverable) and
1301 /// [GAP Set Broadcast Mode](GapCommands::set_broadcast_mode) commands, the advertising
1302 /// type is disallowed. Returns the invalid advertising type.
1303 BadAdvertisingType(crate::types::AdvertisingType),
1304
1305 /// For the [GAP Set Limited Discoverable](GapCommands::set_limited_discoverable)
1306 /// command, the advertising interval is inverted (that is, the max is less than the
1307 /// min). Includes the provided range.
1308 BadAdvertisingInterval(Duration, Duration),
1309
1310 /// For the [GAP Set Authentication Requirement](GapCommands::set_authentication_requirement)
1311 /// command, the encryption key size range is inverted (the max is less than the min). Includes the provided range.
1312 BadEncryptionKeySizeRange(u8, u8),
1313
1314 /// For the [GAP Set Authentication Requirement](GapCommands::set_authentication_requirement)
1315 /// command, the address type must be either Public or Random
1316 BadAddressType(AddressType),
1317
1318 BadPowerAmplifierLevel(u8),
1319
1320 /// For the [GAP Set Authentication Requirement](GapCommands::set_authentication_requirement) and
1321 /// [GAP Pass Key Response](GapCommands::pass_key_response) commands, the provided fixed pin is out of
1322 /// range (must be less than or equal to 999999). Includes the provided PIN.
1323 BadFixedPin(u32),
1324
1325 /// For the [GAP Set Undirected Connectable](GapCommands::set_undirected_connectable) command, the
1326 /// advertising filter policy is not one of the allowed values. Only
1327 /// [AllowConnectionAndScan](crate::host::AdvertisingFilterPolicy::AllowConnectionAndScan) and
1328 /// [WhiteListConnectionAndScan](crate::host::AdvertisingFilterPolicy::WhiteListConnectionAndScan) are
1329 /// allowed.
1330 BadAdvertisingFilterPolicy(crate::host::AdvertisingFilterPolicy),
1331
1332 /// For the [GAP Update Advertising Data](GapCommands::update_advertising_data) and
1333 /// [GAP Set Broadcast Mode](GapCommands::set_broadcast_mode) commands, the advertising data
1334 /// is too long. It must be 31 bytes or less. The length of the provided data is returned.
1335 BadAdvertisingDataLength(usize),
1336
1337 /// For the [GAP Terminate](GapCommands::terminate) command, the termination reason was
1338 /// not one of the allowed reason. The reason is returned.
1339 BadTerminationReason(crate::Status),
1340
1341 /// For the [GAP Start Auto Connection Establishment](GapCommands::start_auto_connection_establishment_procedure) or
1342 /// [GAP Start Selective Connection Establishment](GapCommands::start_selective_connection_establishment_procedure) commands, the
1343 /// provided [white list](AutoConnectionEstablishmentParameters::white_list) has more than 33
1344 /// or 35 entries, respectively, which would cause the command to be longer than 255 bytes.
1345 ///
1346 /// For the [GAP Set Broadcast Mode](GapCommands::set_broadcast_mode), the provided
1347 /// [white list](BroadcastModeParameters::white_list) the maximum number of entries ranges
1348 /// from 31 to 35, depending on the length of the advertising data.
1349 WhiteListTooLong,
1350
1351 /// For the [GAP Terminate Procedure](GapCommands::terminate_gap_procedure) command, the
1352 /// provided bitfield had no bits set.
1353 NoProcedure,
1354}
1355
1356fn to_conn_interval_value(d: Duration) -> u16 {
1357 // Connection interval value: T = N * 1.25 ms
1358 // We have T, we need to return N.
1359 // N = T / 1.25 ms
1360 // = 4 * T / 5 ms
1361 let millis = (d.as_secs() * 1000) as u32 + d.subsec_millis();
1362 (4 * millis / 5) as u16
1363}
1364
1365fn to_connection_length_value(d: Duration) -> u16 {
1366 // Connection interval value: T = N * 0.625 ms
1367 // We have T, we need to return N.
1368 // N = T / 0.625 ms
1369 // = T / 625 us
1370 // 1600 = 1_000_000 / 625
1371 (1600 * d.as_secs() as u32 + (d.subsec_micros() / 625)) as u16
1372}
1373
1374/// Parameters for the
1375/// [`set_limited_discoverable`](GapCommands::set_limited_discoverable) and
1376/// [`set_discoverable`](GapCommands::set_discoverable) commands.
1377#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1378pub struct DiscoverableParameters<'a, 'b> {
1379 /// Advertising method for the device.
1380 ///
1381 /// Must be
1382 /// [ConnectableUndirected](crate::host::AdvertisingType::ConnectableUndirected),
1383 /// [ScannableUndirected](crate::host::AdvertisingType::ScannableUndirected), or
1384 /// [NonConnectableUndirected](crate::host::AdvertisingType::NonConnectableUndirected).
1385 pub advertising_type: AdvertisingType,
1386
1387 /// Range of advertising for non-directed advertising.
1388 ///
1389 /// If not provided, the GAP will use default values (1.28 seconds).
1390 ///
1391 /// Range for both limits: 20 ms to 10.24 seconds. The second value must be greater than or
1392 /// equal to the first.
1393 pub advertising_interval: Option<(Duration, Duration)>,
1394
1395 /// Address type for this device.
1396 pub address_type: OwnAddressType,
1397
1398 /// Filter policy for this device.
1399 pub filter_policy: AdvertisingFilterPolicy,
1400
1401 /// Name of the device.
1402 pub local_name: Option<LocalName<'a>>,
1403
1404 /// Service UUID list as defined in the Bluetooth spec, v4.1, Vol 3, Part C, Section 11.
1405 ///
1406 /// Must be 31 bytes or fewer.
1407 pub advertising_data: &'b [u8],
1408
1409 /// Expected length of the connection to the peripheral.
1410 pub conn_interval: (Option<Duration>, Option<Duration>),
1411}
1412
1413impl<'a, 'b> DiscoverableParameters<'a, 'b> {
1414 // 14 fixed-size parameters, one parameter of up to 31 bytes, and one of up to 248 bytes.
1415 const MAX_LENGTH: usize = 14 + 31 + 248;
1416
1417 fn validate(&self) -> Result<(), Error> {
1418 match self.advertising_type {
1419 AdvertisingType::ConnectableUndirected
1420 | AdvertisingType::ScannableUndirected
1421 | AdvertisingType::NonConnectableUndirected => (),
1422 _ => return Err(Error::BadAdvertisingType(self.advertising_type)),
1423 }
1424
1425 if let Some(interval) = self.advertising_interval {
1426 if interval.0 > interval.1 {
1427 return Err(Error::BadAdvertisingInterval(interval.0, interval.1));
1428 }
1429 }
1430
1431 if let (Some(min), Some(max)) = self.conn_interval {
1432 if min > max {
1433 return Err(Error::BadConnectionInterval(min, max));
1434 }
1435 }
1436
1437 Ok(())
1438 }
1439
1440 fn copy_into_slice(&self, bytes: &mut [u8]) -> usize {
1441 const NO_SPECIFIC_CONN_INTERVAL: u16 = 0x0000;
1442
1443 let len = self.required_len();
1444 assert!(len <= bytes.len());
1445
1446 let no_duration = Duration::from_secs(0);
1447 let no_interval: (Duration, Duration) = (no_duration, no_duration);
1448
1449 bytes[0] = self.advertising_type as u8;
1450 LittleEndian::write_u16(
1451 &mut bytes[1..],
1452 to_connection_length_value(self.advertising_interval.unwrap_or(no_interval).0),
1453 );
1454 LittleEndian::write_u16(
1455 &mut bytes[3..],
1456 to_connection_length_value(self.advertising_interval.unwrap_or(no_interval).1),
1457 );
1458 bytes[5] = self.address_type as u8;
1459 bytes[6] = self.filter_policy as u8;
1460 let advertising_data_len_index = match self.local_name {
1461 None => {
1462 bytes[7] = 0;
1463 7
1464 }
1465 Some(LocalName::Shortened(name)) => {
1466 const AD_TYPE_SHORTENED_LOCAL_NAME: u8 = 0x08;
1467 bytes[7] = 1 + name.len() as u8;
1468 bytes[8] = AD_TYPE_SHORTENED_LOCAL_NAME;
1469 bytes[9..9 + name.len()].copy_from_slice(name);
1470 9 + name.len()
1471 }
1472 Some(LocalName::Complete(name)) => {
1473 const AD_TYPE_COMPLETE_LOCAL_NAME: u8 = 0x09;
1474 bytes[7] = 1 + name.len() as u8;
1475 bytes[8] = AD_TYPE_COMPLETE_LOCAL_NAME;
1476 bytes[9..9 + name.len()].copy_from_slice(name);
1477 9 + name.len()
1478 }
1479 };
1480 bytes[advertising_data_len_index] = self.advertising_data.len() as u8;
1481 bytes[(advertising_data_len_index + 1)
1482 ..(advertising_data_len_index + 1 + self.advertising_data.len())]
1483 .copy_from_slice(self.advertising_data);
1484 let conn_interval_index = advertising_data_len_index + 1 + self.advertising_data.len();
1485 LittleEndian::write_u16(
1486 &mut bytes[conn_interval_index..],
1487 if self.conn_interval.0.is_some() {
1488 to_conn_interval_value(self.conn_interval.0.unwrap())
1489 } else {
1490 NO_SPECIFIC_CONN_INTERVAL
1491 },
1492 );
1493 LittleEndian::write_u16(
1494 &mut bytes[(conn_interval_index + 2)..],
1495 if self.conn_interval.1.is_some() {
1496 to_conn_interval_value(self.conn_interval.1.unwrap())
1497 } else {
1498 NO_SPECIFIC_CONN_INTERVAL
1499 },
1500 );
1501
1502 len
1503 }
1504
1505 fn required_len(&self) -> usize {
1506 let fixed_len = 13;
1507
1508 fixed_len + self.name_len() + self.advertising_data.len()
1509 }
1510
1511 fn name_len(&self) -> usize {
1512 // The serialized name includes one byte indicating the type of name. That byte is not
1513 // included if the name is empty.
1514 match self.local_name {
1515 Some(LocalName::Shortened(bytes)) | Some(LocalName::Complete(bytes)) => 1 + bytes.len(),
1516 None => 0,
1517 }
1518 }
1519}
1520
1521/// Allowed types for the local name.
1522#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1523pub enum LocalName<'a> {
1524 /// The shortened local name.
1525 Shortened(&'a [u8]),
1526
1527 /// The complete local name.
1528 Complete(&'a [u8]),
1529}
1530
1531/// Parameters for the
1532/// [`set_undirected_connectable`](GapCommands::set_undirected_connectable) command.
1533#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1534pub struct UndirectedConnectableParameters {
1535 /// Range of advertising interval for advertising.
1536 ///
1537 /// Range for both limits: 20 ms to 10.24 seconds. The second value must be greater than or
1538 /// equal to the first.
1539 pub advertising_interval: (Duration, Duration),
1540
1541 /// Address type of this device.
1542 pub own_address_type: OwnAddressType,
1543
1544 /// filter policy for this device
1545 pub filter_policy: AdvertisingFilterPolicy,
1546}
1547
1548impl UndirectedConnectableParameters {
1549 const LENGTH: usize = 6;
1550
1551 fn validate(&self) -> Result<(), Error> {
1552 const MIN_DURATION: Duration = Duration::from_millis(20);
1553 const MAX_DURATION: Duration = Duration::from_millis(10240);
1554
1555 match self.filter_policy {
1556 AdvertisingFilterPolicy::AllowConnectionAndScan
1557 | AdvertisingFilterPolicy::WhiteListConnectionAndScan => {}
1558 _ => return Err(Error::BadAdvertisingFilterPolicy(self.filter_policy)),
1559 }
1560
1561 if self.advertising_interval.0 < MIN_DURATION
1562 || self.advertising_interval.1 > MAX_DURATION
1563 || self.advertising_interval.0 > self.advertising_interval.1
1564 {
1565 return Err(Error::BadAdvertisingInterval(
1566 self.advertising_interval.0,
1567 self.advertising_interval.1,
1568 ));
1569 }
1570
1571 Ok(())
1572 }
1573
1574 fn copy_into_slice(&self, bytes: &mut [u8]) {
1575 assert_eq!(bytes.len(), Self::LENGTH);
1576
1577 LittleEndian::write_u16(
1578 &mut bytes[0..],
1579 to_connection_length_value(self.advertising_interval.0),
1580 );
1581 LittleEndian::write_u16(
1582 &mut bytes[2..],
1583 to_connection_length_value(self.advertising_interval.1),
1584 );
1585
1586 bytes[4] = self.own_address_type as u8;
1587 bytes[5] = self.filter_policy as u8;
1588 }
1589}
1590
1591/// Parameters for the
1592/// [`set_direct_connectable`](GapCommands::set_direct_connectable) command.
1593#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1594pub struct DirectConnectableParameters {
1595 /// Address type of this device.
1596 pub own_address_type: OwnAddressType,
1597
1598 /// Advertising method for the device.
1599 ///
1600 /// Must be
1601 /// [ConnectableDirectedHighDutyCycle](crate::host::AdvertisingType::ConnectableDirectedHighDutyCycle),
1602 /// or
1603 /// [ConnectableDirectedLowDutyCycle](crate::host::AdvertisingType::ConnectableDirectedLowDutyCycle).
1604 pub advertising_type: AdvertisingType,
1605
1606 /// Initiator's Bluetooth address.
1607 pub initiator_address: BdAddrType,
1608
1609 /// Range of advertising interval for advertising.
1610 ///
1611 /// Range for both limits: 20 ms to 10.24 seconds. The second value must be greater than or
1612 /// equal to the first.
1613 pub advertising_interval: (Duration, Duration),
1614}
1615
1616impl DirectConnectableParameters {
1617 const LENGTH: usize = 13;
1618
1619 fn validate(&self) -> Result<(), Error> {
1620 const MIN_DURATION: Duration = Duration::from_millis(20);
1621 const MAX_DURATION: Duration = Duration::from_millis(10240);
1622
1623 match self.advertising_type {
1624 AdvertisingType::ConnectableDirectedHighDutyCycle
1625 | AdvertisingType::ConnectableDirectedLowDutyCycle => (),
1626 _ => return Err(Error::BadAdvertisingType(self.advertising_type)),
1627 }
1628
1629 if self.advertising_interval.0 < MIN_DURATION
1630 || self.advertising_interval.1 > MAX_DURATION
1631 || self.advertising_interval.0 > self.advertising_interval.1
1632 {
1633 return Err(Error::BadAdvertisingInterval(
1634 self.advertising_interval.0,
1635 self.advertising_interval.1,
1636 ));
1637 }
1638
1639 Ok(())
1640 }
1641
1642 fn copy_into_slice(&self, bytes: &mut [u8]) {
1643 assert_eq!(bytes.len(), Self::LENGTH);
1644
1645 bytes[0] = self.own_address_type as u8;
1646
1647 bytes[1] = self.advertising_type as u8;
1648 self.initiator_address.copy_into_slice(&mut bytes[2..9]);
1649 LittleEndian::write_u16(
1650 &mut bytes[9..],
1651 to_connection_length_value(self.advertising_interval.0),
1652 );
1653 LittleEndian::write_u16(
1654 &mut bytes[11..],
1655 to_connection_length_value(self.advertising_interval.1),
1656 );
1657 }
1658}
1659
1660/// I/O capabilities available for the [GAP Set I/O Capability](GapCommands::set_io_capability) command.
1661#[repr(u8)]
1662#[derive(Copy, Clone, Debug)]
1663#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1664pub enum IoCapability {
1665 /// Display Only
1666 Display = 0x00,
1667 /// Display yes/no
1668 DisplayConfirm = 0x01,
1669 /// Keyboard Only
1670 Keyboard = 0x02,
1671 /// No Input, no output
1672 None = 0x03,
1673 /// Keyboard display
1674 KeyboardDisplay = 0x04,
1675}
1676
1677/// Parameters for the [GAP Set Authentication Requirement](GapCommands::set_authentication_requirement) command.
1678#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1679pub struct AuthenticationRequirements {
1680 /// Is bonding required?
1681 pub bonding_required: bool,
1682
1683 /// Is MITM (man-in-the-middle) protection required?
1684 pub mitm_protection_required: bool,
1685
1686 /// is secure connection support required
1687 pub secure_connection_support: SecureConnectionSupport,
1688
1689 /// is keypress notification support required
1690 pub keypress_notification_support: bool,
1691
1692 /// Minimum and maximum size of the encryption key.
1693 pub encryption_key_size_range: (u8, u8),
1694
1695 /// Pin to use during the pairing process.
1696 pub fixed_pin: Pin,
1697
1698 /// identity address type.
1699 pub identity_address_type: AddressType,
1700}
1701
1702impl AuthenticationRequirements {
1703 const LENGTH: usize = 12;
1704
1705 fn validate(&self) -> Result<(), Error> {
1706 if self.encryption_key_size_range.0 > self.encryption_key_size_range.1 {
1707 return Err(Error::BadEncryptionKeySizeRange(
1708 self.encryption_key_size_range.0,
1709 self.encryption_key_size_range.1,
1710 ));
1711 }
1712
1713 if let Pin::Fixed(pin) = self.fixed_pin {
1714 if pin > 999_999 {
1715 return Err(Error::BadFixedPin(pin));
1716 }
1717 }
1718
1719 if self.identity_address_type != AddressType::Public
1720 && self.identity_address_type != AddressType::Random
1721 {
1722 return Err(Error::BadAddressType(self.identity_address_type));
1723 }
1724
1725 Ok(())
1726 }
1727
1728 fn copy_into_slice(&self, bytes: &mut [u8]) {
1729 assert_eq!(bytes.len(), Self::LENGTH);
1730
1731 bytes[0] = self.bonding_required as u8;
1732 bytes[1] = self.mitm_protection_required as u8;
1733 bytes[2] = self.secure_connection_support as u8;
1734 bytes[3] = self.keypress_notification_support as u8;
1735 bytes[4] = self.encryption_key_size_range.0;
1736 bytes[5] = self.encryption_key_size_range.1;
1737 match self.fixed_pin {
1738 Pin::Requested => {
1739 bytes[6] = 1;
1740 bytes[7..11].copy_from_slice(&[0; 4]);
1741 }
1742 Pin::Fixed(pin) => {
1743 bytes[6] = 0;
1744 LittleEndian::write_u32(&mut bytes[7..11], pin);
1745 }
1746 }
1747 bytes[11] = self.identity_address_type as u8;
1748 }
1749}
1750
1751/// Options for [`out_of_band_auth`](AuthenticationRequirements::out_of_band_auth).
1752#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1753pub enum OutOfBandAuthentication {
1754 /// Out Of Band authentication not enabled
1755 Disabled,
1756 /// Out Of Band authentication enabled; includes the OOB data.
1757 Enabled([u8; 16]),
1758}
1759
1760/// Options for [`secure_connection_support`](AuthenticationRequirements)
1761#[derive(Clone, Copy)]
1762#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1763pub enum SecureConnectionSupport {
1764 NotSupported = 0x00,
1765 Optional = 0x01,
1766 Mandatory = 0x02,
1767}
1768
1769/// Options for [`fixed_pin`](AuthenticationRequirements).
1770#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1771pub enum Pin {
1772 /// Do not use fixed pin during the pairing process. In this case, GAP will generate a
1773 /// [GAP Pass Key Request](crate::vendor::event::VendorEvent::GapPassKeyRequest) event to the host.
1774 Requested,
1775
1776 /// Use a fixed pin during pairing. The provided value is used as the PIN, and must be 999999 or
1777 /// less.
1778 Fixed(u32),
1779}
1780
1781/// Options for the [GAP Authorization Response](GapCommands::authorization_response).
1782#[repr(u8)]
1783#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1784pub enum Authorization {
1785 /// Accept the connection.
1786 Authorized = 0x01,
1787 /// Reject the connection.
1788 Rejected = 0x02,
1789}
1790
1791#[cfg(not(feature = "defmt"))]
1792bitflags::bitflags! {
1793 /// Roles for a [GAP service](GapCommands::init).
1794 pub struct Role: u8 {
1795 /// Peripheral
1796 const PERIPHERAL = 0x01;
1797 /// Broadcaster
1798 const BROADCASTER = 0x02;
1799 /// Central Device
1800 const CENTRAL = 0x04;
1801 /// Observer
1802 const OBSERVER = 0x08;
1803 }
1804}
1805
1806#[cfg(feature = "defmt")]
1807defmt::bitflags! {
1808 /// Roles for a [GAP service](GapCommands::init).
1809 pub struct Role: u8 {
1810 /// Peripheral
1811 const PERIPHERAL = 0x01;
1812 /// Broadcaster
1813 const BROADCASTER = 0x02;
1814 /// Central Device
1815 const CENTRAL = 0x04;
1816 /// Observer
1817 const OBSERVER = 0x08;
1818 }
1819}
1820
1821/// Indicates the type of address being used in the advertising packets, for the
1822/// [`set_nonconnectable`](GapCommands::set_nonconnectable).
1823#[repr(u8)]
1824#[derive(Copy, Clone, Debug, PartialEq)]
1825#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1826pub enum AddressType {
1827 /// Public device address.
1828 Public = 0x00,
1829 /// Static random device address.
1830 Random = 0x01,
1831 /// Controller generates Resolvable Private Address.
1832 ResolvablePrivate = 0x02,
1833 /// Controller generates Resolvable Private Address. based on the local IRK from resolving
1834 /// list.
1835 NonResolvablePrivate = 0x03,
1836}
1837
1838/// Available types of advertising data.
1839#[repr(u8)]
1840#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1841pub enum AdvertisingDataType {
1842 /// Flags
1843 Flags = 0x01,
1844 /// 16-bit service UUID
1845 Uuid16 = 0x02,
1846 /// Complete list of 16-bit service UUIDs
1847 UuidCompleteList16 = 0x03,
1848 /// 32-bit service UUID
1849 Uuid32 = 0x04,
1850 /// Complete list of 32-bit service UUIDs
1851 UuidCompleteList32 = 0x05,
1852 /// 128-bit service UUID
1853 Uuid128 = 0x06,
1854 /// Complete list of 128-bit service UUIDs.
1855 UuidCompleteList128 = 0x07,
1856 /// Shortened local name
1857 ShortenedLocalName = 0x08,
1858 /// Complete local name
1859 CompleteLocalName = 0x09,
1860 /// Transmitter power level
1861 TxPowerLevel = 0x0A,
1862 /// Serurity Manager TK Value
1863 SecurityManagerTkValue = 0x10,
1864 /// Serurity Manager out-of-band flags
1865 SecurityManagerOutOfBandFlags = 0x11,
1866 /// Connection interval
1867 PeripheralConnectionInterval = 0x12,
1868 /// Service solicitation list, 16-bit UUIDs
1869 SolicitUuidList16 = 0x14,
1870 /// Service solicitation list, 32-bit UUIDs
1871 SolicitUuidList32 = 0x15,
1872 /// Service data
1873 ServiceData = 0x16,
1874 /// Manufacturer-specific data
1875 ManufacturerSpecificData = 0xFF,
1876}
1877
1878#[cfg(not(feature = "defmt"))]
1879bitflags::bitflags! {
1880 /// Event types for [GAP Set Event Mask](GapCommands::set_event_mask).
1881 #[derive(Debug, Clone, Copy)]
1882 pub struct EventFlags: u16 {
1883 /// [Limited Discoverable](::event::VendorEvent::GapLimitedDiscoverableTimeout)
1884 const LIMITED_DISCOVERABLE_TIMEOUT = 0x0001;
1885 /// [Pairing Complete](::event::VendorEvent::GapPairingComplete)
1886 const PAIRING_COMPLETE = 0x0002;
1887 /// [Pass Key Request](::event::VendorEvent::GapPassKeyRequest)
1888 const PASS_KEY_REQUEST = 0x0004;
1889 /// [Authorization Request](::event::VendorEvent::GapAuthorizationRequest)
1890 const AUTHORIZATION_REQUEST = 0x0008;
1891 /// [Peripheral Security Initiated](::event::VendorEvent::GapPeripheralSecurityInitiated).
1892 const PERIPHERAL_SECURITY_INITIATED = 0x0010;
1893 /// [Bond Lost](::event::VendorEvent::GapBondLost)
1894 const BOND_LOST = 0x0020;
1895 }
1896}
1897
1898#[cfg(feature = "defmt")]
1899defmt::bitflags! {
1900 /// Event types for [GAP Set Event Mask](GapCommands::set_event_mask).
1901 pub struct EventFlags: u16 {
1902 /// [Limited Discoverable](::event::VendorEvent::GapLimitedDiscoverableTimeout)
1903 const LIMITED_DISCOVERABLE_TIMEOUT = 0x0001;
1904 /// [Pairing Complete](::event::VendorEvent::GapPairingComplete)
1905 const PAIRING_COMPLETE = 0x0002;
1906 /// [Pass Key Request](::event::VendorEvent::GapPassKeyRequest)
1907 const PASS_KEY_REQUEST = 0x0004;
1908 /// [Authorization Request](::event::VendorEvent::GapAuthorizationRequest)
1909 const AUTHORIZATION_REQUEST = 0x0008;
1910 /// [Peripheral Security Initiated](::event::VendorEvent::GapPeripheralSecurityInitiated).
1911 const PERIPHERAL_SECURITY_INITIATED = 0x0010;
1912 /// [Bond Lost](::event::VendorEvent::GapBondLost)
1913 const BOND_LOST = 0x0020;
1914 }
1915}
1916
1917/// Parameters for the [GAP Limited Discovery](GapCommands::start_limited_discovery_procedure) and
1918/// [GAP General Discovery](GapCommands::start_general_discovery_procedure) procedures.
1919pub struct DiscoveryProcedureParameters {
1920 /// Scanning window for the discovery procedure.
1921 pub scan_window: ScanWindow,
1922
1923 /// Address type of this device.
1924 pub own_address_type: crate::host::OwnAddressType,
1925
1926 /// If true, duplicate devices are filtered out.
1927 pub filter_duplicates: bool,
1928}
1929
1930impl DiscoveryProcedureParameters {
1931 const LENGTH: usize = 6;
1932
1933 fn copy_into_slice(&self, bytes: &mut [u8]) {
1934 assert_eq!(bytes.len(), Self::LENGTH);
1935
1936 self.scan_window.copy_into_slice(&mut bytes[0..4]);
1937 bytes[4] = self.own_address_type as u8;
1938 bytes[5] = self.filter_duplicates as u8;
1939 }
1940}
1941
1942/// Parameters for the [GAP Name Discovery](GapCommands::start_name_discovery_procedure)
1943/// procedure.
1944pub struct NameDiscoveryProcedureParameters {
1945 /// Scanning window for the discovery procedure.
1946 pub scan_window: ScanWindow,
1947
1948 /// Address of the connected device
1949 pub peer_address: crate::host::PeerAddrType,
1950
1951 /// Address type of this device.
1952 pub own_address_type: crate::host::OwnAddressType,
1953
1954 /// Connection interval parameters.
1955 pub conn_interval: ConnectionInterval,
1956
1957 /// Expected connection length
1958 pub expected_connection_length: ExpectedConnectionLength,
1959}
1960
1961impl NameDiscoveryProcedureParameters {
1962 const LENGTH: usize = 24;
1963
1964 fn copy_into_slice(&self, bytes: &mut [u8]) {
1965 assert_eq!(bytes.len(), Self::LENGTH);
1966
1967 self.scan_window.copy_into_slice(&mut bytes[0..4]);
1968 self.peer_address.copy_into_slice(&mut bytes[4..11]);
1969 bytes[11] = self.own_address_type as u8;
1970 self.conn_interval.copy_into_slice(&mut bytes[12..20]);
1971 self.expected_connection_length
1972 .copy_into_slice(&mut bytes[20..24]);
1973 }
1974}
1975
1976/// Parameters for the
1977/// [GAP Start Auto Connection Establishment](GapCommands::start_auto_connection_establishment_procedure) command.
1978pub struct AutoConnectionEstablishmentParameters<'a> {
1979 /// Scanning window for connection establishment.
1980 pub scan_window: ScanWindow,
1981
1982 /// Address type of this device.
1983 pub own_address_type: crate::host::OwnAddressType,
1984
1985 /// Connection interval parameters.
1986 pub conn_interval: ConnectionInterval,
1987
1988 /// Expected connection length
1989 pub expected_connection_length: ExpectedConnectionLength,
1990
1991 /// Addresses to white-list for automatic connection.
1992 pub white_list: &'a [crate::host::PeerAddrType],
1993}
1994
1995impl<'a> AutoConnectionEstablishmentParameters<'a> {
1996 const MAX_LENGTH: usize = 249;
1997
1998 fn validate(&self) -> Result<(), Error> {
1999 const MAX_WHITE_LIST_LENGTH: usize = 33;
2000 if self.white_list.len() > MAX_WHITE_LIST_LENGTH {
2001 return Err(Error::WhiteListTooLong);
2002 }
2003
2004 Ok(())
2005 }
2006
2007 fn copy_into_slice(&self, bytes: &mut [u8]) -> usize {
2008 let len = self.len();
2009 assert!(bytes.len() >= len);
2010
2011 self.scan_window.copy_into_slice(&mut bytes[0..4]);
2012 bytes[4] = self.own_address_type as u8;
2013 self.conn_interval.copy_into_slice(&mut bytes[5..13]);
2014 self.expected_connection_length
2015 .copy_into_slice(&mut bytes[13..17]);
2016
2017 let index = 17;
2018
2019 bytes[index] = self.white_list.len() as u8;
2020 let index = index + 1;
2021 for i in 0..self.white_list.len() {
2022 self.white_list[i].copy_into_slice(&mut bytes[(index + 7 * i)..(index + 7 * (i + 1))]);
2023 }
2024
2025 len
2026 }
2027
2028 fn len(&self) -> usize {
2029 let reconn_addr_len = 0;
2030 18 + reconn_addr_len + 7 * self.white_list.len()
2031 }
2032}
2033
2034/// Parameters for the
2035/// [GAP Start General Connection Establishment](GapCommands::start_general_connection_establishment_procedure) command.
2036pub struct GeneralConnectionEstablishmentParameters {
2037 /// passive or active scanning. With passive scanning, no scan request PDUs are sent
2038 pub scan_type: ScanType,
2039
2040 /// Scanning window for connection establishment.
2041 pub scan_window: ScanWindow,
2042
2043 /// Address type of this device.
2044 pub own_address_type: crate::host::OwnAddressType,
2045
2046 /// Scanning filter policy.
2047 ///
2048 /// # Note
2049 /// if privacy is enabled, filter policy can only assume values
2050 /// [Accept All](ScanFilterPolicy::AcceptAll) or
2051 /// [Addressed To This Device](ScanFilterPolicy::AddressedToThisDevice)
2052 pub filter_policy: ScanFilterPolicy,
2053
2054 /// If true, only report unique devices.
2055 pub filter_duplicates: bool,
2056}
2057
2058impl GeneralConnectionEstablishmentParameters {
2059 const LENGTH: usize = 8;
2060
2061 fn copy_into_slice(&self, bytes: &mut [u8]) {
2062 assert!(bytes.len() >= Self::LENGTH);
2063
2064 bytes[0] = self.scan_type as u8;
2065 self.scan_window.copy_into_slice(&mut bytes[1..5]);
2066 bytes[5] = self.filter_policy as u8;
2067 bytes[6] = self.own_address_type as u8;
2068 bytes[7] = self.filter_duplicates as u8;
2069 }
2070}
2071
2072/// Parameters for the
2073/// [GAP Start Selective Connection Establishment](GapCommands::start_selective_connection_establishment_procedure) command.
2074pub struct SelectiveConnectionEstablishmentParameters<'a> {
2075 /// Type of scanning
2076 pub scan_type: crate::host::ScanType,
2077
2078 /// Scanning window for connection establishment.
2079 pub scan_window: ScanWindow,
2080
2081 /// Address type of this device.
2082 pub own_address_type: crate::host::OwnAddressType,
2083
2084 /// Scanning filter policy.
2085 ///
2086 /// # Note
2087 /// if privacy is enabled, filter policy can only assume values
2088 /// [Accept All](ScanFilterPolicy::AcceptAll) or
2089 /// [Whitelist Addressed to this Device](ScanFilterPolicy::WhiteListAddressedToThisDevice)
2090 pub filter_policy: ScanFilterPolicy,
2091
2092 /// If true, only report unique devices.
2093 pub filter_duplicates: bool,
2094
2095 /// Addresses to white-list for automatic connection.
2096 pub white_list: &'a [crate::host::PeerAddrType],
2097}
2098
2099impl<'a> SelectiveConnectionEstablishmentParameters<'a> {
2100 const MAX_LENGTH: usize = 254;
2101
2102 fn validate(&self) -> Result<(), Error> {
2103 const MAX_WHITE_LIST_LENGTH: usize = 35;
2104 if self.white_list.len() > MAX_WHITE_LIST_LENGTH {
2105 return Err(Error::WhiteListTooLong);
2106 }
2107
2108 Ok(())
2109 }
2110
2111 fn copy_into_slice(&self, bytes: &mut [u8]) -> usize {
2112 let len = self.len();
2113 assert!(bytes.len() >= len);
2114
2115 bytes[0] = self.scan_type as u8;
2116 self.scan_window.copy_into_slice(&mut bytes[1..5]);
2117 bytes[5] = self.own_address_type as u8;
2118 bytes[6] = self.filter_policy as u8;
2119 bytes[7] = self.filter_duplicates as u8;
2120 bytes[8] = self.white_list.len() as u8;
2121 for i in 0..self.white_list.len() {
2122 self.white_list[i].copy_into_slice(&mut bytes[(9 + 7 * i)..(9 + 7 * (i + 1))]);
2123 }
2124
2125 len
2126 }
2127
2128 fn len(&self) -> usize {
2129 9 + 7 * self.white_list.len()
2130 }
2131}
2132
2133/// The parameters for the [GAP Name Discovery](GapCommands::start_name_discovery_procedure)
2134/// and [GAP Create Connection](GapCommands::create_connection) commands are identical.
2135pub type ConnectionParameters = NameDiscoveryProcedureParameters;
2136
2137#[cfg(not(feature = "defmt"))]
2138bitflags::bitflags! {
2139 /// Roles for a [GAP service](GapCommands::init).
2140 pub struct Procedure: u8 {
2141 /// [Limited Discovery](GapCommands::start_limited_discovery_procedure) procedure.
2142 const LIMITED_DISCOVERY = 0x01;
2143 /// [General Discovery](GapCommands::start_general_discovery_procedure) procedure.
2144 const GENERAL_DISCOVERY = 0x02;
2145 /// [Name Discovery](GapCommands::start_name_discovery_procedure) procedure.
2146 const NAME_DISCOVERY = 0x04;
2147 /// [Auto Connection Establishment](GapCommands::auto_connection_establishment).
2148 const AUTO_CONNECTION_ESTABLISHMENT = 0x08;
2149 /// [General Connection Establishment](GapCommands::general_connection_establishment).
2150 const GENERAL_CONNECTION_ESTABLISHMENT = 0x10;
2151 /// [Selective Connection Establishment](GapCommands::selective_connection_establishment).
2152 const SELECTIVE_CONNECTION_ESTABLISHMENT = 0x20;
2153 /// [Direct Connection Establishment](GapCommands::direct_connection_establishment).
2154 const DIRECT_CONNECTION_ESTABLISHMENT = 0x40;
2155 /// [Observation](GapCommands::start_observation_procedure) procedure.
2156 const OBSERVATION = 0x80;
2157 }
2158}
2159
2160#[cfg(feature = "defmt")]
2161defmt::bitflags! {
2162 /// Roles for a [GAP service](GapCommands::init).
2163 pub struct Procedure: u8 {
2164 /// [Limited Discovery](GapCommands::start_limited_discovery_procedure) procedure.
2165 const LIMITED_DISCOVERY = 0x01;
2166 /// [General Discovery](GapCommands::start_general_discovery_procedure) procedure.
2167 const GENERAL_DISCOVERY = 0x02;
2168 /// [Name Discovery](GapCommands::start_name_discovery_procedure) procedure.
2169 const NAME_DISCOVERY = 0x04;
2170 /// [Auto Connection Establishment](GapCommands::auto_connection_establishment).
2171 const AUTO_CONNECTION_ESTABLISHMENT = 0x08;
2172 /// [General Connection Establishment](GapCommands::general_connection_establishment).
2173 const GENERAL_CONNECTION_ESTABLISHMENT = 0x10;
2174 /// [Selective Connection Establishment](GapCommands::selective_connection_establishment).
2175 const SELECTIVE_CONNECTION_ESTABLISHMENT = 0x20;
2176 /// [Direct Connection Establishment](GapCommands::direct_connection_establishment).
2177 const DIRECT_CONNECTION_ESTABLISHMENT = 0x40;
2178 /// [Observation](GapCommands::start_observation_procedure) procedure.
2179 const OBSERVATION = 0x80;
2180 }
2181}
2182
2183/// Parameters for the [`start_connection_update`](GapCommands::start_connection_update)
2184/// command.
2185pub struct ConnectionUpdateParameters {
2186 /// Handle of the connection for which the update procedure has to be started.
2187 pub conn_handle: crate::ConnectionHandle,
2188
2189 /// Updated connection interval for the connection.
2190 pub conn_interval: ConnectionInterval,
2191
2192 /// Expected length of connection event needed for this connection.
2193 pub expected_connection_length: ExpectedConnectionLength,
2194}
2195
2196impl ConnectionUpdateParameters {
2197 const LENGTH: usize = 14;
2198
2199 fn copy_into_slice(&self, bytes: &mut [u8]) {
2200 LittleEndian::write_u16(&mut bytes[0..2], self.conn_handle.0);
2201 self.conn_interval.copy_into_slice(&mut bytes[2..10]);
2202 self.expected_connection_length
2203 .copy_into_slice(&mut bytes[10..14]);
2204 }
2205}
2206
2207/// Parameters for the [`send_pairing_request`](GapCommands::send_pairing_request)
2208/// command.
2209pub struct PairingRequest {
2210 /// Handle of the connection for which the pairing request has to be sent.
2211 pub conn_handle: crate::ConnectionHandle,
2212
2213 /// Whether pairing request has to be sent if the device is previously bonded or not. If false,
2214 /// the pairing request is sent only if the device has not previously bonded.
2215 pub force_rebond: bool,
2216}
2217
2218impl PairingRequest {
2219 const LENGTH: usize = 2;
2220
2221 fn copy_into_slice(&self, bytes: &mut [u8]) {
2222 assert!(bytes.len() >= Self::LENGTH);
2223
2224 LittleEndian::write_u16(&mut bytes[0..2], self.conn_handle.0);
2225 }
2226}
2227
2228/// Parameters for the [GAP Set Broadcast Mode](GapCommands::set_broadcast_mode) command.
2229pub struct BroadcastModeParameters<'a, 'b> {
2230 /// Advertising type and interval.
2231 ///
2232 /// Only the [ScannableUndirected](crate::types::AdvertisingType::ScannableUndirected) and
2233 /// [NonConnectableUndirected](crate::types::AdvertisingType::NonConnectableUndirected).
2234 pub advertising_interval: crate::types::AdvertisingInterval,
2235
2236 /// Type of this device's address.
2237 ///
2238 /// A privacy enabled device uses either a
2239 /// [resolvable private address](AddressType::ResolvablePrivate) or a
2240 /// [non-resolvable private](AddressType::NonResolvablePrivate) address.
2241 pub own_address_type: AddressType,
2242
2243 /// Advertising data used by the device when advertising.
2244 ///
2245 /// Must be 31 bytes or fewer.
2246 pub advertising_data: &'a [u8],
2247
2248 /// Addresses to add to the white list.
2249 ///
2250 /// Each address takes up 7 bytes (1 byte for the type, 6 for the address). The full length of
2251 /// this packet must not exceed 255 bytes. The white list must be less than a maximum of between
2252 /// 31 and 35 entries, depending on the length of
2253 /// [`advertising_data`](BroadcastModeParameters::advertising_data). Shorter advertising data
2254 /// allows more white list entries.
2255 pub white_list: &'b [crate::host::PeerAddrType],
2256}
2257
2258impl<'a, 'b> BroadcastModeParameters<'a, 'b> {
2259 const MAX_LENGTH: usize = 255;
2260
2261 fn validate(&self) -> Result<(), Error> {
2262 const MAX_ADVERTISING_DATA_LENGTH: usize = 31;
2263
2264 match self.advertising_interval.advertising_type() {
2265 crate::types::AdvertisingType::ScannableUndirected
2266 | crate::types::AdvertisingType::NonConnectableUndirected => (),
2267 other => return Err(Error::BadAdvertisingType(other)),
2268 }
2269
2270 if self.advertising_data.len() > MAX_ADVERTISING_DATA_LENGTH {
2271 return Err(Error::BadAdvertisingDataLength(self.advertising_data.len()));
2272 }
2273
2274 if self.len() > Self::MAX_LENGTH {
2275 return Err(Error::WhiteListTooLong);
2276 }
2277
2278 Ok(())
2279 }
2280
2281 fn len(&self) -> usize {
2282 5 + // advertising_interval
2283 1 + // own_address_type
2284 1 + self.advertising_data.len() + // advertising_data
2285 1 + 7 * self.white_list.len() // white_list
2286 }
2287
2288 fn copy_into_slice(&self, bytes: &mut [u8]) -> usize {
2289 assert!(self.len() <= bytes.len());
2290
2291 self.advertising_interval.copy_into_slice(&mut bytes[0..5]);
2292 bytes[5] = self.own_address_type as u8;
2293 bytes[6] = self.advertising_data.len() as u8;
2294 bytes[7..7 + self.advertising_data.len()].copy_from_slice(self.advertising_data);
2295 bytes[7 + self.advertising_data.len()] = self.white_list.len() as u8;
2296
2297 let mut index = 8 + self.advertising_data.len();
2298 for addr in self.white_list.iter() {
2299 addr.copy_into_slice(&mut bytes[index..index + 7]);
2300 index += 7;
2301 }
2302
2303 index
2304 }
2305}
2306
2307/// Parameters for the [GAP Start Observation Procedure](GapCommands::start_observation_procedure)
2308/// command.
2309pub struct ObservationProcedureParameters {
2310 /// Scanning window.
2311 pub scan_window: crate::types::ScanWindow,
2312
2313 /// Active or passive scanning
2314 pub scan_type: crate::host::ScanType,
2315
2316 /// Address type of this device.
2317 pub own_address_type: AddressType,
2318
2319 /// If true, do not report duplicate events in the
2320 /// [advertising report](crate::event::Event::LeAdvertisingReport).
2321 pub filter_duplicates: bool,
2322
2323 /// Scanning filter policy
2324 pub filter_policy: ScanFilterPolicy,
2325}
2326
2327impl ObservationProcedureParameters {
2328 const LENGTH: usize = 8;
2329
2330 fn copy_into_slice(&self, bytes: &mut [u8]) {
2331 assert!(bytes.len() >= Self::LENGTH);
2332
2333 self.scan_window.copy_into_slice(&mut bytes[0..4]);
2334 bytes[4] = self.scan_type as u8;
2335 bytes[5] = self.own_address_type as u8;
2336 bytes[6] = self.filter_duplicates as u8;
2337 bytes[7] = self.filter_policy as u8;
2338 }
2339}
2340
2341/// Parameters for [GAP Numeric Comparison Confirm Yes or No](crate::vendor::command::gap::GapCommands::numeric_comparison_value_confirm_yes_no)
2342pub struct NumericComparisonValueConfirmYesNoParameters {
2343 conn_handle: ConnectionHandle,
2344 confirm_yes_no: bool,
2345}
2346
2347impl NumericComparisonValueConfirmYesNoParameters {
2348 const LENGTH: usize = 3;
2349
2350 fn copy_into_slice(&self, bytes: &mut [u8]) {
2351 assert!(bytes.len() >= Self::LENGTH);
2352
2353 LittleEndian::write_u16(&mut bytes[0..2], self.conn_handle.0);
2354 bytes[2] = self.confirm_yes_no as u8;
2355 }
2356}
2357
2358/// Parameter for [GAP Passkey Input](GapCommands::passkey_input)
2359pub enum InputType {
2360 EntryStarted = 0x00,
2361 DigitEntered = 0x01,
2362 DigitErased = 0x02,
2363 Cleared = 0x03,
2364 EntryCompleted = 0x04,
2365}
2366
2367#[derive(Clone, Copy)]
2368pub enum OobDataType {
2369 /// TK (LP v.4.1)
2370 TK,
2371 /// Random (SC)
2372 Random,
2373 /// Confirm (SC)
2374 Confirm,
2375}
2376
2377#[derive(Clone, Copy)]
2378pub enum OobDeviceType {
2379 Local = 0x00,
2380 Remote = 0x01,
2381}
2382
2383/// Parameters for [GAP Set OOB Data](GapCommands::set_oob_data)
2384pub struct SetOobDataParameters {
2385 /// OOB Device type
2386 device_type: OobDeviceType,
2387 /// Identity address
2388 address: BdAddrType,
2389 /// OOB Data type
2390 oob_data_type: OobDataType,
2391 /// Pairing Data received through OOB from remote device
2392 oob_data: [u8; 16],
2393}
2394
2395impl SetOobDataParameters {
2396 const LENGTH: usize = 26;
2397
2398 fn copy_into_slice(&self, bytes: &mut [u8]) {
2399 assert!(bytes.len() >= Self::LENGTH);
2400
2401 bytes[0] = self.device_type as u8;
2402 self.address.copy_into_slice(&mut bytes[1..8]);
2403 bytes[9] = self.oob_data_type as u8;
2404 bytes[10..26].copy_from_slice(&self.oob_data)
2405 }
2406}
2407
2408/// Parameter for [GAP Add Devices to List](GapCommands::add_devices_to_list)
2409pub enum AddDeviceToListMode {
2410 /// Append to the resolving list only
2411 AppendResoling = 0x00,
2412 /// clear and set the resolving list only
2413 ClearAndSetResolving = 0x01,
2414 /// append to the whitelist only
2415 AppendWhitelist = 0x02,
2416 /// clear and set the whitelist only
2417 ClearAndSetWhitelist = 0x03,
2418 /// apppend to both resolving and white lists
2419 AppendBoth = 0x04,
2420 /// clear and set both resolving and white lists
2421 ClearAndSetBoth = 0x05,
2422}
2423
2424/// Parameters for [GAP Additional Beacon Start](GapCommands::additional_beacon_start)
2425pub struct AdditonalBeaconStartParameters {
2426 /// Advertising interval
2427 pub advertising_interval: (Duration, Duration),
2428 /// advertising channel map
2429 pub advertising_channel_map: Channels,
2430 /// Own address type
2431 pub own_address_type: BdAddrType,
2432 /// Power amplifier output level. Range: 0x00 .. 0x23
2433 pub pa_level: u8,
2434}
2435
2436impl AdditonalBeaconStartParameters {
2437 const LENGTH: usize = 13;
2438
2439 fn validate(&self) -> Result<(), Error> {
2440 const AMPLIFIER_MAX: u8 = 0x23;
2441
2442 if self.pa_level > AMPLIFIER_MAX {
2443 return Err(Error::BadPowerAmplifierLevel(self.pa_level));
2444 }
2445
2446 Ok(())
2447 }
2448
2449 fn copy_into_slice(&self, bytes: &mut [u8]) {
2450 assert!(bytes.len() >= Self::LENGTH);
2451
2452 LittleEndian::write_u16(
2453 &mut bytes[0..],
2454 to_connection_length_value(self.advertising_interval.0),
2455 );
2456 LittleEndian::write_u16(
2457 &mut bytes[2..],
2458 to_connection_length_value(self.advertising_interval.1),
2459 );
2460 bytes[4] = self.advertising_channel_map.bits();
2461 self.own_address_type.copy_into_slice(&mut bytes[5..12]);
2462 bytes[12] = self.pa_level;
2463 }
2464}
2465
2466/// Params for the [adv_set_config](GapCommands::adv_set_config) command
2467pub struct AdvSetConfig {
2468 /// Bitmap of extended advertising modes
2469 pub adv_mode: AdvertisingMode,
2470 /// Used to identify an advertising set
2471 pub adv_handle: AdvertisingHandle,
2472 /// Type of advertising event
2473 pub adv_event_properties: AdvertisingEvent,
2474 /// Advertising interval
2475 pub adv_interval: ExtendedAdvertisingInterval,
2476 /// Advertising channel map
2477 pub primary_adv_channel_map: Channels,
2478 /// Own address type.
2479 ///
2480 /// If privacy is disabled, the address can be public or static random, otherwise,
2481 /// it can be a resolvable private address or a non-resolvabble private address.
2482 pub own_addr_type: OwnAddressType,
2483 /// Public device address, random device addressm public identity address, or random
2484 /// (static) identity address of the device to be connected.
2485 pub peer_addr: BdAddrType,
2486 /// Advertising filter policy
2487 pub adv_filter_policy: AdvertisingFilterPolicy,
2488 /// Advertising TX power. Units; dBm.
2489 ///
2490 /// Values;
2491 /// - -127 .. 20
2492 pub adv_tx_power: u8,
2493 /// Secondary advertising maximum skip.
2494 ///
2495 /// Values:
2496 /// - 0x00: `AUX_QDV_IND` shall be sent prior to the next advertising event
2497 /// - 0x01 .. 0xFF: Maximum advertising events to the Controller can skip
2498 /// before sending the `AUX_QDV_IND` packets on the secondary physical channel.
2499 pub secondary_adv_max_skip: u8,
2500 /// Secondary advertising PHY
2501 pub secondary_adv_phy: AdvertisingPhy,
2502 /// Value of advertising SID subfield in the ADI field of the PDU.
2503 ///
2504 /// Values:
2505 /// - 0x00 .. 0x0F
2506 pub adv_sid: u8,
2507 /// Scan request notifications
2508 pub scan_req_notification_enable: bool,
2509}
2510
2511impl AdvSetConfig {
2512 const LENGTH: usize = 25;
2513
2514 fn copy_into_slice(&self, bytes: &mut [u8]) {
2515 assert_eq!(bytes.len(), Self::LENGTH);
2516
2517 bytes[0] = self.adv_mode.bits();
2518 bytes[1] = self.adv_handle.0;
2519 LittleEndian::write_u16(&mut bytes[2..], self.adv_event_properties.bits());
2520 self.adv_interval.copy_into_slice(&mut bytes[4..]);
2521 bytes[12] = self.primary_adv_channel_map.bits();
2522 bytes[13] = self.own_addr_type as u8;
2523 self.peer_addr.copy_into_slice(&mut bytes[14..]);
2524 bytes[21] = self.adv_filter_policy as u8;
2525 bytes[22] = self.adv_tx_power;
2526 bytes[23] = self.secondary_adv_max_skip;
2527 bytes[24] = self.adv_sid;
2528 bytes[25] = self.scan_req_notification_enable as u8;
2529 }
2530}
2531
2532/// Params for the [adv_set_enable](GapCommands::adv_set_enable) command
2533pub struct AdvSetEnable<'a> {
2534 /// Enable/Disable advertising
2535 pub enable: bool,
2536 /// Number of advertising sets.
2537 ///
2538 /// Values
2539 /// - 0x00: disable all advertising sets
2540 /// - 0x01 .. 0x3F: Number of advertising sets to enable or disable
2541 pub num_sets: u8,
2542 /// Advertising sets
2543 pub adv_set: &'a [AdvSet],
2544}
2545
2546impl<'a> AdvSetEnable<'a> {
2547 const MAX_LENGTH: usize = 254;
2548
2549 fn copy_into_slice(&self, bytes: &mut [u8]) {
2550 assert!(bytes.len() >= Self::MAX_LENGTH);
2551
2552 bytes[0] = self.enable as u8;
2553 bytes[1] = self.num_sets;
2554 for (idx, set) in self.adv_set.iter().enumerate() {
2555 set.copy_into_slice(&mut bytes[2 + (idx * 4)..]);
2556 }
2557 }
2558}
2559
2560/// Params for the [adv_set_advertising_data](GapCommands::adv_set_advertising_data) command
2561pub struct AdvSetAdvertisingData<'a> {
2562 /// Used to identify an advertising set
2563 pub adv_handle: AdvertisingHandle,
2564 /// Advertising operation
2565 pub operation: AdvertisingOperation,
2566 /// Fragment preference. If set to `true`, the Controller may fragment all data, else
2567 /// the Controller should not fragment or should minimize fragmentation of data
2568 pub fragment: bool,
2569 /// Data formatted as defined in Bluetooth spec. v.5.4 [Vol 3, Part C, 11].
2570 pub data: &'a [u8],
2571}
2572
2573impl<'a> AdvSetAdvertisingData<'a> {
2574 const MAX_LENGTH: usize = 255;
2575
2576 fn copy_into_slice(&self, bytes: &mut [u8]) {
2577 assert!(bytes.len() >= Self::MAX_LENGTH);
2578
2579 bytes[0] = self.adv_handle.0;
2580 bytes[1] = self.operation as u8;
2581 bytes[2] = (!self.fragment) as u8;
2582 let length = self.data.len();
2583 bytes[3] = length as u8;
2584 bytes[4..(4 + length)].copy_from_slice(self.data);
2585 }
2586}