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}