stm32wb_hci/vendor/event/
command.rs

1//! Return parameters for vendor-specific commands.
2//!
3//! This module defines the parameters returned in the Command Complete event for vendor-specific
4//! commands.  These commands are defined for the BlueNRG controller, but are not standard HCI
5//! commands.
6
7use crate::{require_len, require_len_at_least};
8use byteorder::{ByteOrder, LittleEndian};
9use core::convert::{TryFrom, TryInto};
10use core::fmt::{Debug, Formatter, Result as FmtResult};
11use core::time::Duration;
12
13use super::AttributeHandle;
14
15/// Vendor-specific commands that may generate the
16/// [Command Complete](crate::event::command::ReturnParameters::Vendor) event. If the commands have defined
17/// return parameters, they are included in the enum.
18#[allow(clippy::large_enum_variant)]
19#[derive(Clone, Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum VendorReturnParameters {
22    /// Parameters returned by the
23    /// [HAL Get Firmware Revision](crate::vendor::command::hal::HalCommands::get_firmware_revision) command.
24    HalGetFirmwareRevision(HalFirmwareRevision),
25
26    /// Status returned by the [HAL Write Config Data](crate::vendor::command::hal::HalCommands::write_config_data)
27    /// command.
28    HalWriteConfigData(crate::Status),
29
30    /// Parameters returned by the [HAL Read Config Data](crate::vendor::command::hal::HalCommands::read_config_data)
31    /// command.
32    HalReadConfigData(HalConfigData),
33
34    /// Status returned by the [HAL Set Tx Power Level](crate::vendor::command::hal::HalCommands::set_tx_power_level)
35    /// command.
36    HalSetTxPowerLevel(crate::Status),
37
38    /// Status returned by the
39    /// [HAL Device Standby](crate::vendor::command::hal::HalCommands::device_standby) command.
40    HalDeviceStandby(crate::Status),
41
42    /// Parameters returned by the
43    /// [HAL Get Tx Test Packet Count](crate::vendor::command::hal::HalCommands::get_tx_test_packet_count) command.
44    HalGetTxTestPacketCount(HalTxTestPacketCount),
45
46    /// Status returned by the [HAL Start Tone](crate::vendor::command::hal::HalCommands::start_tone) command.
47    HalStartTone(crate::Status),
48
49    /// Status returned by the [HAL Stop Tone](crate::vendor::command::hal::HalCommands::stop_tone) command.
50    HalStopTone(crate::Status),
51
52    /// Status returned by the [HAL Get Link Status](crate::vendor::command::hal::HalCommands::get_link_status) command.
53    HalGetLinkStatus(HalLinkStatus),
54
55    /// Parameters returned by the [HAL Get Anchor Period](crate::vendor::command::hal::HalCommands::get_anchor_period)
56    /// command.
57    HalGetAnchorPeriod(HalAnchorPeriod),
58
59    /// Parameters returned by the [HAL Get PM Debug Info](crate::vendor::command::hal::HalCommands::get_pm_debug_info)
60    /// command.
61    HalGetPmDebugInfo(HalPmDebugInfo),
62
63    /// Parameters returned by the [HAL Read RSSI](crate::vendor::command::hal::HalCommands::read_rssi)
64    /// command.
65    HalReadRssi(u8),
66
67    /// Parameters returned by the [HAL Read Radio Register](crate::vendor::command::hal::HalCommands::read_radio_reg)
68    /// command.
69    HalReadRadioReg(u8),
70
71    /// Parameters returned by the [HAL Read Raw RSSI](crate::vendor::command::hal::HalCommands::read_raw_rssi)
72    /// command.
73    HalReadRawRssi(u8),
74
75    /// Status returned by the
76    /// [GAP Set Non-Discoverable](crate::vendor::command::gap::GapCommands::gap_set_nondiscoverable)
77    /// command.
78    GapSetNonDiscoverable(crate::Status),
79
80    /// Status returned by the
81    /// [GAP Set Discoverable](crate::vendor::command::gap::GapCommands::set_discoverable)
82    /// command.
83    GapSetDiscoverable(crate::Status),
84
85    /// Status returned by the
86    /// [GAP Set Direct Connectable](crate::vendor::command::gap::GapCommands::set_direct_connectable) command.
87    GapSetDirectConnectable(crate::Status),
88
89    /// Status returned by the [GAP Set IO Capability](crate::vendor::command::gap::GapCommands::set_io_capability)
90    /// command.
91    GapSetIoCapability(crate::Status),
92
93    /// Status returned by the
94    /// [GAP Set Authentication Requirement](crate::vendor::command::gap::GapCommands::set_authentication_requirement) command.
95    GapSetAuthenticationRequirement(crate::Status),
96
97    /// Status returned by the
98    /// [GAP Set Authorization Requirement](crate::vendor::command::gap::GapCommands::set_authorization_requirement) command.
99    GapSetAuthorizationRequirement(crate::Status),
100
101    /// Status returned by the
102    /// [GAP Pass Key Response](crate::vendor::command::gap::GapCommands::pass_key_response)
103    /// command.
104    GapPassKeyResponse(crate::Status),
105
106    /// Status returned by the
107    /// [GAP Authorization Response](crate::vendor::command::gap::GapCommands::authorization_response) command.
108    GapAuthorizationResponse(crate::Status),
109
110    /// Parameters returned by the [GAP Init](crate::vendor::command::gap::GapCommands::init) command.
111    GapInit(GapInit),
112
113    /// Parameters returned by the
114    /// [GAP Set Non-Connectable](crate::vendor::command::gap::GapCommands::set_nonconnectable) command.
115    GapSetNonConnectable(crate::Status),
116
117    /// Parameters returned by the
118    /// [GAP Set Undirected Connectable](crate::vendor::command::gap::GapCommands::set_undirected_connectable) command.
119    GapSetUndirectedConnectable(crate::Status),
120
121    /// Parameters returned by the
122    /// [GAP Update Advertising Data](crate::vendor::command::gap::GapCommands::update_advertising_data) command.
123    GapUpdateAdvertisingData(crate::Status),
124
125    /// Parameters returned by the
126    /// [GAP Delete AD Type](crate::vendor::command::gap::GapCommands::delete_ad_type)
127    /// command.
128    GapDeleteAdType(crate::Status),
129
130    /// Parameters returned by the
131    /// [GAP Get Security Level](crate::vendor::command::gap::GapCommands::get_security_level) command.
132    GapGetSecurityLevel(GapSecurityLevel),
133
134    /// Parameters returned by the
135    /// [GAP Set Event Mask](crate::vendor::command::gap::GapCommands::set_event_mask)
136    /// command.
137    GapSetEventMask(crate::Status),
138
139    /// Parameters returned by the
140    /// [GAP Configure White List](crate::vendor::command::gap::GapCommands::configure_white_list) command.
141    GapConfigureWhiteList(crate::Status),
142
143    /// Parameters returned by the
144    /// [GAP Clear Security Database](crate::vendor::command::gap::GapCommands::clear_security_database) command.
145    GapClearSecurityDatabase(crate::Status),
146
147    /// Parameters returned by the
148    /// [GAP Allow Rebond](crate::vendor::command::gap::GapCommands::allow_rebond) command.
149    GapAllowRebond(crate::Status),
150
151    /// Parameters returned by the
152    /// [GAP Terminate Procedure](crate::vendor::command::gap::GapCommands::terminate_gap_procedure) command.
153    GapTerminateProcedure(crate::Status),
154
155    /// Parameters returned by the
156    /// [GAP Resolve Private Address](crate::vendor::command::gap::GapCommands::resolve_private_address) command.
157    GapResolvePrivateAddress(GapResolvePrivateAddress),
158
159    /// Parameters returned by the
160    /// [GAP Get Bonded Devices](crate::vendor::command::gap::GapCommands::get_bonded_devices) command.
161    GapGetBondedDevices(GapBondedDevices),
162
163    /// Parameters returned by the
164    /// [GAP Set Broadcast Mode](crate::vendor::command::gap::GapCommands::set_broadcast_mode) command.
165    GapSetBroadcastMode(crate::Status),
166
167    /// Parameters returned by the
168    /// [GAP Start Observation Procedure](crate::vendor::command::gap::GapCommands::start_observation_procedure) command.
169    GapStartObservationProcedure(crate::Status),
170
171    /// Parameters returned by the
172    /// [GAP Is Device Bonded](crate::vendor::command::gap::GapCommands::is_device_bonded)
173    /// command.
174    GapIsDeviceBonded(crate::Status),
175
176    /// Parameters returned by the
177    /// [GATT Init](crate::vendor::command::gatt::GattCommands::init) command.
178    GattInit(crate::Status),
179
180    /// Parameters returned by the
181    /// [GATT Add Service](crate::vendor::command::gatt::GattCommands::add_service) command.
182    GattAddService(GattService),
183
184    /// Parameters returned by the
185    /// [GATT Include Service](crate::vendor::command::gatt::GattCommands::include_service)
186    /// command.
187    GattIncludeService(GattService),
188
189    /// Parameters returned by the
190    /// [GATT Add Characteristic](crate::vendor::command::gatt::GattCommands::add_characteristic) command.
191    GattAddCharacteristic(GattCharacteristic),
192
193    /// Parameters returned by the
194    /// [GATT Add Characteristic Descriptor](crate::vendor::command::gatt::GattCommands::add_characteristic_descriptor) command.
195    GattAddCharacteristicDescriptor(GattCharacteristicDescriptor),
196
197    /// Parameters returned by the
198    /// [GATT Update Characteristic Value](crate::vendor::command::gatt::GattCommands::update_characteristic_value) command.
199    GattUpdateCharacteristicValue(crate::Status),
200
201    /// Parameters returned by the
202    /// [GATT Delete Characteristic](crate::vendor::command::gatt::GattCommands::delete_characteristic) command.
203    GattDeleteCharacteristic(crate::Status),
204
205    /// Parameters returned by the
206    /// [GATT Delete Service](crate::vendor::command::gatt::GattCommands::delete_service)
207    /// command.
208    GattDeleteService(crate::Status),
209
210    /// Parameters returned by the
211    /// [GATT Delete Included Service](crate::vendor::command::gatt::GattCommands::delete_included_service) command.
212    GattDeleteIncludedService(crate::Status),
213
214    /// Parameters returned by the [GATT Set Event Mask](crate::vendor::command::gatt::GattCommands::set_event_mask)
215    /// command.
216    GattSetEventMask(crate::Status),
217
218    /// Parameters returned by the
219    /// [GATT Write Without Response](crate::vendor::command::gatt::GattCommands::write_without_response) command.
220    GattWriteWithoutResponse(crate::Status),
221
222    /// Parameters returned by the
223    /// [GATT Signed Write Without Response](crate::vendor::command::gatt::GattCommands::signed_write_without_response) command.
224    GattSignedWriteWithoutResponse(crate::Status),
225
226    /// Parameters returned by the
227    /// [GATT Confirm Indication](crate::vendor::command::gatt::GattCommands::confirm_indication) command.
228    GattConfirmIndication(crate::Status),
229
230    /// Parameters returned by the [GATT Write Response](crate::vendor::command::gatt::GattCommands::write_response)
231    /// command.
232    GattWriteResponse(crate::Status),
233
234    /// Parameters returned by the [GATT Allow Read](crate::vendor::command::gatt::GattCommands::allow_read) command.
235    GattAllowRead(crate::Status),
236
237    /// Parameters returned by the
238    /// [GATT Set Security Permission](crate::vendor::command::gatt::GattCommands::set_security_permission) command.
239    GattSetSecurityPermission(crate::Status),
240
241    /// Parameters returned by the
242    /// [GATT Set Descriptor Value](crate::vendor::command::gatt::GattCommands::set_descriptor_value) command.
243    GattSetDescriptorValue(crate::Status),
244
245    /// Parameters returned by the
246    /// [GATT Read Handle Value](crate::vendor::command::gatt::GattCommands::read_handle_value) command.
247    GattReadHandleValue(GattHandleValue),
248
249    /// Parameters returned by the
250    /// [GATT Read Handle Value](crate::vendor::command::gatt::GattCommands::read_handle_value_offset) command.
251    GattReadHandleValueOffset(GattHandleValue),
252
253    /// Parameters returned by the
254    /// [GATT Update Long Characteristic Value](crate::vendor::command::gatt::GattCommands::update_characteristic_value_ext) command.
255    GattUpdateLongCharacteristicValue(crate::Status),
256
257    /// Status returned by the
258    /// [L2CAP Connection Parameter Update Response](crate::vendor::command::l2cap::L2capCommands::connection_parameter_update_response) command.
259    L2CapConnectionParameterUpdateResponse(crate::Status),
260}
261
262impl VendorReturnParameters {
263    pub(crate) fn new(bytes: &[u8]) -> Result<Self, crate::event::Error> {
264        check_len_at_least(bytes, 3)?;
265
266        match crate::Opcode(LittleEndian::read_u16(&bytes[1..])) {
267            crate::vendor::opcode::HAL_GET_FIRMWARE_REVISION => {
268                Ok(VendorReturnParameters::HalGetFirmwareRevision(
269                    to_hal_firmware_revision(&bytes[3..])?,
270                ))
271            }
272            crate::vendor::opcode::HAL_WRITE_CONFIG_DATA => Ok(
273                VendorReturnParameters::HalWriteConfigData(to_status(&bytes[3..])?),
274            ),
275            crate::vendor::opcode::HAL_READ_CONFIG_DATA => Ok(
276                VendorReturnParameters::HalReadConfigData(to_hal_config_data(&bytes[3..])?),
277            ),
278            crate::vendor::opcode::HAL_SET_TX_POWER_LEVEL => Ok(
279                VendorReturnParameters::HalSetTxPowerLevel(to_status(&bytes[3..])?),
280            ),
281            crate::vendor::opcode::HAL_DEVICE_STANDBY => Ok(
282                VendorReturnParameters::HalDeviceStandby(to_status(&bytes[3..])?),
283            ),
284            crate::vendor::opcode::HAL_TX_TEST_PACKET_COUNT => {
285                Ok(VendorReturnParameters::HalGetTxTestPacketCount(
286                    to_hal_tx_test_packet_count(&bytes[3..])?,
287                ))
288            }
289            crate::vendor::opcode::HAL_START_TONE => Ok(VendorReturnParameters::HalStartTone(
290                to_status(&bytes[3..])?,
291            )),
292            crate::vendor::opcode::HAL_STOP_TONE => {
293                Ok(VendorReturnParameters::HalStopTone(to_status(&bytes[3..])?))
294            }
295            crate::vendor::opcode::HAL_GET_LINK_STATUS => Ok(
296                VendorReturnParameters::HalGetLinkStatus(to_hal_link_status(&bytes[3..])?),
297            ),
298            crate::vendor::opcode::HAL_GET_ANCHOR_PERIOD => Ok(
299                VendorReturnParameters::HalGetAnchorPeriod(to_hal_anchor_period(&bytes[3..])?),
300            ),
301            crate::vendor::opcode::HAL_GET_PM_DEBUG_INFO => Ok(
302                VendorReturnParameters::HalGetPmDebugInfo(to_hal_pm_debug_info(&bytes[3..])?),
303            ),
304            crate::vendor::opcode::HAL_READ_RSSI => Ok(VendorReturnParameters::HalReadRssi({
305                require_len!(&bytes[3..], 1);
306                bytes[3]
307            })),
308            crate::vendor::opcode::HAL_READ_RADIO_REG => {
309                Ok(VendorReturnParameters::HalReadRadioReg({
310                    require_len!(&bytes[3..], 1);
311                    bytes[3]
312                }))
313            }
314            crate::vendor::opcode::HAL_READ_RAW_RSSI => {
315                Ok(VendorReturnParameters::HalReadRawRssi({
316                    require_len!(&bytes[3..], 1);
317                    bytes[3]
318                }))
319            }
320            crate::vendor::opcode::GAP_SET_NONDISCOVERABLE => Ok(
321                VendorReturnParameters::GapSetNonDiscoverable(to_status(&bytes[3..])?),
322            ),
323            crate::vendor::opcode::GAP_SET_DISCOVERABLE => Ok(
324                VendorReturnParameters::GapSetDiscoverable(to_status(&bytes[3..])?),
325            ),
326            crate::vendor::opcode::GAP_SET_DIRECT_CONNECTABLE => Ok(
327                VendorReturnParameters::GapSetDirectConnectable(to_status(&bytes[3..])?),
328            ),
329            crate::vendor::opcode::GAP_SET_IO_CAPABILITY => Ok(
330                VendorReturnParameters::GapSetIoCapability(to_status(&bytes[3..])?),
331            ),
332            crate::vendor::opcode::GAP_SET_AUTHENTICATION_REQUIREMENT => Ok(
333                VendorReturnParameters::GapSetAuthenticationRequirement(to_status(&bytes[3..])?),
334            ),
335            crate::vendor::opcode::GAP_SET_AUTHORIZATION_REQUIREMENT => Ok(
336                VendorReturnParameters::GapSetAuthorizationRequirement(to_status(&bytes[3..])?),
337            ),
338            crate::vendor::opcode::GAP_PASS_KEY_RESPONSE => Ok(
339                VendorReturnParameters::GapPassKeyResponse(to_status(&bytes[3..])?),
340            ),
341            crate::vendor::opcode::GAP_AUTHORIZATION_RESPONSE => Ok(
342                VendorReturnParameters::GapAuthorizationResponse(to_status(&bytes[3..])?),
343            ),
344            crate::vendor::opcode::GAP_INIT => {
345                Ok(VendorReturnParameters::GapInit(to_gap_init(&bytes[3..])?))
346            }
347            crate::vendor::opcode::GAP_SET_NONCONNECTABLE => Ok(
348                VendorReturnParameters::GapSetNonConnectable(to_status(&bytes[3..])?),
349            ),
350            crate::vendor::opcode::GAP_SET_UNDIRECTED_CONNECTABLE => Ok(
351                VendorReturnParameters::GapSetUndirectedConnectable(to_status(&bytes[3..])?),
352            ),
353            crate::vendor::opcode::GAP_UPDATE_ADVERTISING_DATA => Ok(
354                VendorReturnParameters::GapUpdateAdvertisingData(to_status(&bytes[3..])?),
355            ),
356            crate::vendor::opcode::GAP_DELETE_AD_TYPE => Ok(
357                VendorReturnParameters::GapDeleteAdType(to_status(&bytes[3..])?),
358            ),
359            crate::vendor::opcode::GAP_GET_SECURITY_LEVEL => Ok(
360                VendorReturnParameters::GapGetSecurityLevel(to_gap_security_level(&bytes[3..])?),
361            ),
362            crate::vendor::opcode::GAP_SET_EVENT_MASK => Ok(
363                VendorReturnParameters::GapSetEventMask(to_status(&bytes[3..])?),
364            ),
365            crate::vendor::opcode::GAP_CONFIGURE_WHITE_LIST => Ok(
366                VendorReturnParameters::GapConfigureWhiteList(to_status(&bytes[3..])?),
367            ),
368            crate::vendor::opcode::GAP_CLEAR_SECURITY_DATABASE => Ok(
369                VendorReturnParameters::GapClearSecurityDatabase(to_status(&bytes[3..])?),
370            ),
371            crate::vendor::opcode::GAP_ALLOW_REBOND => Ok(VendorReturnParameters::GapAllowRebond(
372                to_status(&bytes[3..])?,
373            )),
374            crate::vendor::opcode::GAP_TERMINATE_PROCEDURE => Ok(
375                VendorReturnParameters::GapTerminateProcedure(to_status(&bytes[3..])?),
376            ),
377            crate::vendor::opcode::GAP_RESOLVE_PRIVATE_ADDRESS => {
378                Ok(VendorReturnParameters::GapResolvePrivateAddress(
379                    to_gap_resolve_private_address(&bytes[3..])?,
380                ))
381            }
382            crate::vendor::opcode::GAP_GET_BONDED_DEVICES => Ok(
383                VendorReturnParameters::GapGetBondedDevices(to_gap_bonded_devices(&bytes[3..])?),
384            ),
385            crate::vendor::opcode::GAP_SET_BROADCAST_MODE => Ok(
386                VendorReturnParameters::GapSetBroadcastMode(to_status(&bytes[3..])?),
387            ),
388            crate::vendor::opcode::GAP_START_OBSERVATION_PROCEDURE => Ok(
389                VendorReturnParameters::GapStartObservationProcedure(to_status(&bytes[3..])?),
390            ),
391            crate::vendor::opcode::GAP_IS_DEVICE_BONDED => Ok(
392                VendorReturnParameters::GapIsDeviceBonded(to_status(&bytes[3..])?),
393            ),
394            crate::vendor::opcode::GATT_INIT => {
395                Ok(VendorReturnParameters::GattInit(to_status(&bytes[3..])?))
396            }
397            crate::vendor::opcode::GATT_ADD_SERVICE => Ok(VendorReturnParameters::GattAddService(
398                to_gatt_service(&bytes[3..])?,
399            )),
400            crate::vendor::opcode::GATT_INCLUDE_SERVICE => Ok(
401                VendorReturnParameters::GattIncludeService(to_gatt_service(&bytes[3..])?),
402            ),
403            crate::vendor::opcode::GATT_ADD_CHARACTERISTIC => Ok(
404                VendorReturnParameters::GattAddCharacteristic(to_gatt_characteristic(&bytes[3..])?),
405            ),
406            crate::vendor::opcode::GATT_ADD_CHARACTERISTIC_DESCRIPTOR => {
407                Ok(VendorReturnParameters::GattAddCharacteristicDescriptor(
408                    to_gatt_characteristic_descriptor(&bytes[3..])?,
409                ))
410            }
411            crate::vendor::opcode::GATT_UPDATE_CHARACTERISTIC_VALUE => Ok(
412                VendorReturnParameters::GattUpdateCharacteristicValue(to_status(&bytes[3..])?),
413            ),
414            crate::vendor::opcode::GATT_DELETE_CHARACTERISTIC => Ok(
415                VendorReturnParameters::GattDeleteCharacteristic(to_status(&bytes[3..])?),
416            ),
417            crate::vendor::opcode::GATT_DELETE_SERVICE => Ok(
418                VendorReturnParameters::GattDeleteService(to_status(&bytes[3..])?),
419            ),
420            crate::vendor::opcode::GATT_DELETE_INCLUDED_SERVICE => Ok(
421                VendorReturnParameters::GattDeleteIncludedService(to_status(&bytes[3..])?),
422            ),
423            crate::vendor::opcode::GATT_SET_EVENT_MASK => Ok(
424                VendorReturnParameters::GattSetEventMask(to_status(&bytes[3..])?),
425            ),
426            crate::vendor::opcode::GATT_WRITE_WITHOUT_RESPONSE => Ok(
427                VendorReturnParameters::GattWriteWithoutResponse(to_status(&bytes[3..])?),
428            ),
429            crate::vendor::opcode::GATT_SIGNED_WRITE_WITHOUT_RESPONSE => Ok(
430                VendorReturnParameters::GattSignedWriteWithoutResponse(to_status(&bytes[3..])?),
431            ),
432            crate::vendor::opcode::GATT_CONFIRM_INDICATION => Ok(
433                VendorReturnParameters::GattConfirmIndication(to_status(&bytes[3..])?),
434            ),
435            crate::vendor::opcode::GATT_WRITE_RESPONSE => Ok(
436                VendorReturnParameters::GattWriteResponse(to_status(&bytes[3..])?),
437            ),
438            crate::vendor::opcode::GATT_ALLOW_READ => Ok(VendorReturnParameters::GattAllowRead(
439                to_status(&bytes[3..])?,
440            )),
441            crate::vendor::opcode::GATT_SET_SECURITY_PERMISSION => Ok(
442                VendorReturnParameters::GattSetSecurityPermission(to_status(&bytes[3..])?),
443            ),
444            crate::vendor::opcode::GATT_SET_DESCRIPTOR_VALUE => Ok(
445                VendorReturnParameters::GattSetDescriptorValue(to_status(&bytes[3..])?),
446            ),
447            crate::vendor::opcode::GATT_READ_HANDLE_VALUE => Ok(
448                VendorReturnParameters::GattReadHandleValue(to_gatt_handle_value(&bytes[3..])?),
449            ),
450            crate::vendor::opcode::GATT_READ_HANDLE_VALUE_OFFSET => {
451                Ok(VendorReturnParameters::GattReadHandleValueOffset(
452                    to_gatt_handle_value(&bytes[3..])?,
453                ))
454            }
455            crate::vendor::opcode::GATT_UPDATE_LONG_CHARACTERISTIC_VALUE => Ok(
456                VendorReturnParameters::GattUpdateLongCharacteristicValue(to_status(&bytes[3..])?),
457            ),
458            crate::vendor::opcode::L2CAP_CONN_PARAM_UPDATE_RESP => Ok(
459                VendorReturnParameters::L2CapConnectionParameterUpdateResponse(to_status(
460                    &bytes[3..],
461                )?),
462            ),
463            other => Err(crate::event::Error::UnknownOpcode(other)),
464        }
465    }
466}
467
468fn check_len_at_least(buffer: &[u8], len: usize) -> Result<(), crate::event::Error> {
469    if buffer.len() < len {
470        Err(crate::event::Error::BadLength(buffer.len(), len))
471    } else {
472        Ok(())
473    }
474}
475
476fn to_status(bytes: &[u8]) -> Result<crate::Status, crate::event::Error> {
477    require_len_at_least!(bytes, 1);
478    bytes[0].try_into().map_err(crate::event::rewrap_bad_status)
479}
480
481/// Parameters returned by the
482/// [HAL Get Firmware Revision](crate::vendor::command::hal::HalCommands::get_firmware_revision) command.
483#[derive(Clone, Debug)]
484#[cfg_attr(feature = "defmt", derive(defmt::Format))]
485pub struct HalFirmwareRevision {
486    /// Did the command fail, and if so, how?
487    pub status: crate::Status,
488
489    /// The firmware revision number.
490    pub revision: u16,
491}
492
493fn to_hal_firmware_revision(bytes: &[u8]) -> Result<HalFirmwareRevision, crate::event::Error> {
494    require_len!(bytes, 3);
495
496    Ok(HalFirmwareRevision {
497        status: to_status(bytes)?,
498        revision: LittleEndian::read_u16(&bytes[1..]),
499    })
500}
501
502/// Parameters returned by the [HAL Read Config Data](crate::vendor::command::hal::HalCommands::read_config_data)
503/// command.
504#[derive(Clone, Debug)]
505#[cfg_attr(feature = "defmt", derive(defmt::Format))]
506pub struct HalConfigData {
507    /// Did the command fail, and if so, how?
508    pub status: crate::Status,
509
510    /// Requested value.
511    ///
512    /// The value is requested by offset, and distinguished upon return by length only. This means
513    /// that this event cannot distinguish between the 16-byte encryption keys
514    /// ([EncryptionRoot](crate::vendor::command::hal::ConfigParameter::EncryptionRoot) and
515    /// [IdentityRoot](crate::vendor::command::hal::ConfigParameter::IdentityRoot)) or between the single-byte values
516    /// ([LinkLayerOnly](crate::vendor::command::hal::ConfigParameter::LinkLayerOnly) or
517    /// [Role](crate::vendor::command::hal::ConfigParameter::Role)).
518    pub value: HalConfigParameter,
519}
520
521/// Potential values that can be fetched by
522/// [HAL Read Config Data](crate::vendor::command::hal::HalCommands::read_config_data).
523#[derive(Clone, Debug, PartialEq)]
524#[cfg_attr(feature = "defmt", derive(defmt::Format))]
525pub enum HalConfigParameter {
526    /// Bluetooth public address. Corresponds to
527    /// [PublicAddress](crate::vendor::command::hal::ConfigParameter::PublicAddress).
528    PublicAddress(crate::BdAddr),
529
530    /// Bluetooth random address. Corresponds to
531    /// [RandomAddress](crate::vendor::command::hal::ConfigParameter::RandomAddress).
532    RandomAddress(crate::BdAddr),
533
534    /// Diversifier used to derive CSRK (connection signature resolving key).  Corresponds to
535    /// [Diversifier](crate::vendor::command::hal::ConfigParameter::Diversifier).
536    Diversifier(u16),
537
538    /// A requested encryption key. Corresponds to either
539    /// [EncryptionRoot](crate::vendor::command::hal::ConfigParameter::EncryptionRoot) or
540    /// [IdentityRoot](crate::vendor::command::hal::ConfigParameter::IdentityRoot).
541    EncryptionKey(crate::host::EncryptionKey),
542
543    /// A single-byte value. Corresponds to either
544    /// [LinkLayerOnly](crate::vendor::command::hal::ConfigParameter::LinkLayerOnly) or
545    /// [Role](crate::vendor::command::hal::ConfigParameter::Role).
546    Byte(u8),
547}
548
549fn to_hal_config_data(bytes: &[u8]) -> Result<HalConfigData, crate::event::Error> {
550    require_len_at_least!(bytes, 2);
551    Ok(HalConfigData {
552        status: to_status(bytes)?,
553        value: to_hal_config_parameter(&bytes[1..])?,
554    })
555}
556
557fn to_hal_config_parameter(bytes: &[u8]) -> Result<HalConfigParameter, crate::event::Error> {
558    match bytes.len() {
559        6 => {
560            let mut buf = [0; 6];
561            buf.copy_from_slice(bytes);
562
563            Ok(HalConfigParameter::PublicAddress(crate::BdAddr(buf)))
564        }
565        2 => Ok(HalConfigParameter::Diversifier(LittleEndian::read_u16(
566            bytes,
567        ))),
568        16 => {
569            let mut buf = [0; 16];
570            buf.copy_from_slice(bytes);
571
572            Ok(HalConfigParameter::EncryptionKey(
573                crate::host::EncryptionKey(buf),
574            ))
575        }
576        1 => Ok(HalConfigParameter::Byte(bytes[0])),
577        other => Err(crate::event::Error::Vendor(
578            super::VendorError::BadConfigParameterLength(other),
579        )),
580    }
581}
582
583/// Parameters returned by the
584/// [HAL Get Tx Test Packet Count](crate::vendor::command::hal::HalCommands::get_tx_test_packet_count) command.
585#[derive(Clone, Debug)]
586#[cfg_attr(feature = "defmt", derive(defmt::Format))]
587pub struct HalTxTestPacketCount {
588    /// Did the command fail, and if so, how?
589    pub status: crate::Status,
590
591    /// Number of packets sent during the last Direct TX test.
592    pub packet_count: u32,
593}
594
595fn to_hal_tx_test_packet_count(bytes: &[u8]) -> Result<HalTxTestPacketCount, crate::event::Error> {
596    require_len!(bytes, 5);
597    Ok(HalTxTestPacketCount {
598        status: to_status(bytes)?,
599        packet_count: LittleEndian::read_u32(&bytes[1..]),
600    })
601}
602
603/// Parameters returned by the [HAL Get Link Status](crate::vendor::command::hal::HalCommands::get_link_status) command.
604#[derive(Clone, Debug)]
605#[cfg_attr(feature = "defmt", derive(defmt::Format))]
606pub struct HalLinkStatus {
607    /// Did the command fail, and if so, how?
608    pub status: crate::Status,
609
610    /// State of the client connections.
611    pub clients: [ClientStatus; 8],
612}
613
614/// State of a client connection.
615#[derive(Copy, Clone, Debug, PartialEq)]
616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
617pub struct ClientStatus {
618    /// Link state for the client.
619    pub state: LinkState,
620
621    /// Connection handle for the client
622    pub conn_handle: crate::ConnectionHandle,
623}
624
625/// Potential states for a connection.
626#[derive(Copy, Clone, Debug, PartialEq)]
627#[cfg_attr(feature = "defmt", derive(defmt::Format))]
628pub enum LinkState {
629    /// Idle
630    Idle,
631    /// Advertising
632    Advertising,
633    /// Connected in peripheral role
634    ConnectedAsPeripheral,
635    /// Scanning
636    Scanning,
637    /// Reserved
638    Reserved,
639    /// Connected in primary role
640    ConnectedAsPrimary,
641    /// TX Test
642    TxTest,
643    /// RX Test
644    RxTest,
645}
646
647impl TryFrom<u8> for LinkState {
648    type Error = super::VendorError;
649
650    fn try_from(value: u8) -> Result<Self, Self::Error> {
651        match value {
652            0 => Ok(LinkState::Idle),
653            1 => Ok(LinkState::Advertising),
654            2 => Ok(LinkState::ConnectedAsPeripheral),
655            3 => Ok(LinkState::Scanning),
656            4 => Ok(LinkState::Reserved),
657            5 => Ok(LinkState::ConnectedAsPrimary),
658            6 => Ok(LinkState::TxTest),
659            7 => Ok(LinkState::RxTest),
660            _ => Err(super::VendorError::UnknownLinkState(value)),
661        }
662    }
663}
664
665fn to_hal_link_status(bytes: &[u8]) -> Result<HalLinkStatus, crate::event::Error> {
666    require_len!(bytes, 25);
667
668    let mut status = HalLinkStatus {
669        status: to_status(&bytes[0..])?,
670        clients: [ClientStatus {
671            state: LinkState::Idle,
672            conn_handle: crate::ConnectionHandle(0),
673        }; 8],
674    };
675
676    for client in 0..8 {
677        status.clients[client].state = bytes[1 + client]
678            .try_into()
679            .map_err(crate::event::Error::Vendor)?;
680        status.clients[client].conn_handle = crate::ConnectionHandle(LittleEndian::read_u16(
681            &bytes[9 + 2 * client..9 + 2 * (client + 1)],
682        ));
683    }
684
685    Ok(status)
686}
687
688/// Parameters returned by the [HAL Get Anchor Period](crate::vendor::command::hal::HalCommands::get_anchor_period)
689/// command.
690#[derive(Clone, Debug)]
691#[cfg_attr(feature = "defmt", derive(defmt::Format))]
692pub struct HalAnchorPeriod {
693    /// Did the command fail, and if so, how?
694    pub status: crate::Status,
695
696    /// Duration between the beginnings of sniff anchor points.
697    pub anchor_interval: Duration,
698
699    /// Maximum available size that can be allocated to a new connection slot.
700    pub max_slot: Duration,
701}
702
703fn to_hal_anchor_period(bytes: &[u8]) -> Result<HalAnchorPeriod, crate::event::Error> {
704    require_len!(bytes, 9);
705
706    Ok(HalAnchorPeriod {
707        status: to_status(bytes)?,
708        anchor_interval: Duration::from_micros(
709            625 * u64::from(LittleEndian::read_u32(&bytes[1..5])),
710        ),
711        max_slot: Duration::from_micros(625 * u64::from(LittleEndian::read_u32(&bytes[5..9]))),
712    })
713}
714
715/// Parameters returned by the [HAL Get PM Debug Info](crate::vendor::command::hal::HalCommands::get_pm_debug_info)
716/// command.
717#[derive(Clone, Debug)]
718#[cfg_attr(feature = "defmt", derive(defmt::Format))]
719pub struct HalPmDebugInfo {
720    /// MBlocks allocated for TXing
721    pub tx: u8,
722    /// MBlocks allocated for RXing
723    pub rx: u8,
724    /// Overall allocated MBlocks
725    pub mblocks: u8,
726}
727
728fn to_hal_pm_debug_info(bytes: &[u8]) -> Result<HalPmDebugInfo, crate::event::Error> {
729    require_len!(bytes, 3);
730
731    Ok(HalPmDebugInfo {
732        tx: bytes[0],
733        rx: bytes[1],
734        mblocks: bytes[2],
735    })
736}
737
738/// Parameters returned by the [GAP Init](crate::vendor::command::gap::GapCommands::init) command.
739#[derive(Copy, Clone, Debug)]
740#[cfg_attr(feature = "defmt", derive(defmt::Format))]
741pub struct GapInit {
742    /// Did the command fail, and if so, how?
743    ///
744    /// Should be one of:
745    /// - [Success](crate::Status::Success)
746    /// - [InvalidParameters](crate::Status::InvalidParameters)
747    pub status: crate::Status,
748
749    /// Handle for the GAP service
750    pub service_handle: AttributeHandle,
751
752    /// Handle for the device name characteristic added to the GAP service.
753    pub dev_name_handle: AttributeHandle,
754
755    /// Handle for the appearance characteristic added to the GAP service.
756    pub appearance_handle: AttributeHandle,
757}
758
759fn to_gap_init(bytes: &[u8]) -> Result<GapInit, crate::event::Error> {
760    require_len!(bytes, 7);
761
762    Ok(GapInit {
763        status: to_status(bytes)?,
764        service_handle: AttributeHandle(LittleEndian::read_u16(&bytes[1..])),
765        dev_name_handle: AttributeHandle(LittleEndian::read_u16(&bytes[3..])),
766        appearance_handle: AttributeHandle(LittleEndian::read_u16(&bytes[5..])),
767    })
768}
769
770/// Parameters returned by the [GAP Get Security Level](crate::vendor::command::gap::GapCommands::get_security_level)
771/// command.
772#[derive(Copy, Clone, Debug)]
773#[cfg_attr(feature = "defmt", derive(defmt::Format))]
774pub struct GapSecurityLevel {
775    /// Did the command fail, and if so, how?
776    pub status: crate::Status,
777
778    /// Is MITM (man-in-the-middle) protection required?
779    pub mitm_protection_required: bool,
780
781    /// Is bonding required?
782    pub bonding_required: bool,
783
784    /// Is out-of-band data present?
785    pub out_of_band_data_present: bool,
786
787    /// Is a pass key required, and if so, how is it generated?
788    pub pass_key_required: PassKeyRequirement,
789}
790
791/// Options for pass key generation.
792#[derive(Copy, Clone, Debug, PartialEq)]
793#[cfg_attr(feature = "defmt", derive(defmt::Format))]
794pub enum PassKeyRequirement {
795    /// A pass key is not required.
796    NotRequired,
797    /// A fixed pin is present which is being used.
798    FixedPin,
799    /// Pass key required for pairing. An event will be generated when required.
800    Generated,
801}
802
803impl TryFrom<u8> for PassKeyRequirement {
804    type Error = super::VendorError;
805
806    fn try_from(value: u8) -> Result<Self, Self::Error> {
807        match value {
808            0x00 => Ok(PassKeyRequirement::NotRequired),
809            0x01 => Ok(PassKeyRequirement::FixedPin),
810            0x02 => Ok(PassKeyRequirement::Generated),
811            _ => Err(super::VendorError::BadPassKeyRequirement(value)),
812        }
813    }
814}
815
816fn to_boolean(value: u8) -> Result<bool, super::VendorError> {
817    match value {
818        0 => Ok(false),
819        1 => Ok(true),
820        _ => Err(super::VendorError::BadBooleanValue(value)),
821    }
822}
823
824fn to_gap_security_level(bytes: &[u8]) -> Result<GapSecurityLevel, crate::event::Error> {
825    require_len!(bytes, 5);
826
827    Ok(GapSecurityLevel {
828        status: to_status(&bytes[0..])?,
829        mitm_protection_required: to_boolean(bytes[1]).map_err(crate::event::Error::Vendor)?,
830        bonding_required: to_boolean(bytes[2]).map_err(crate::event::Error::Vendor)?,
831        out_of_band_data_present: to_boolean(bytes[3]).map_err(crate::event::Error::Vendor)?,
832        pass_key_required: bytes[4].try_into().map_err(crate::event::Error::Vendor)?,
833    })
834}
835
836/// Parameters returned by the
837/// [GAP Resolve Private Address](crate::vendor::command::gap::GapCommands::resolve_private_address) command.
838#[derive(Copy, Clone, Debug)]
839#[cfg_attr(feature = "defmt", derive(defmt::Format))]
840pub struct GapResolvePrivateAddress {
841    /// Did the command fail, and if so, how?
842    pub status: crate::Status,
843
844    /// If the address was successfully resolved, the peer address is returned.  This value is
845    /// `None` if the address could not be resolved.
846    pub bd_addr: Option<crate::BdAddr>,
847}
848
849fn to_gap_resolve_private_address(
850    bytes: &[u8],
851) -> Result<GapResolvePrivateAddress, crate::event::Error> {
852    let status = to_status(bytes)?;
853    if status == crate::Status::Success {
854        require_len!(bytes, 7);
855
856        let mut addr = [0; 6];
857        addr.copy_from_slice(&bytes[1..7]);
858
859        Ok(GapResolvePrivateAddress {
860            status,
861            bd_addr: Some(crate::BdAddr(addr)),
862        })
863    } else {
864        Ok(GapResolvePrivateAddress {
865            status,
866            bd_addr: None,
867        })
868    }
869}
870
871/// Parameters returned by the [GAP Get Bonded Devices](crate::vendor::command::gap::GapCommands::get_bonded_devices)
872/// command.
873#[derive(Copy, Clone)]
874#[cfg_attr(feature = "defmt", derive(defmt::Format))]
875pub struct GapBondedDevices {
876    /// Did the command fail, and if so, how?
877    pub status: crate::Status,
878
879    // Number of peer addresses in the event, and a buffer that can hold all of the addresses.
880    address_count: usize,
881    address_buffer: [crate::BdAddrType; MAX_ADDRESSES],
882}
883
884// Max packet size (255 bytes) less non-address data (4 bytes) divided by peer address size (7):
885const MAX_ADDRESSES: usize = 35;
886
887impl GapBondedDevices {
888    /// Return an iterator over the bonded device addresses.
889    pub fn bonded_addresses(&self) -> &[crate::BdAddrType] {
890        &self.address_buffer[..self.address_count]
891    }
892}
893
894impl Debug for GapBondedDevices {
895    fn fmt(&self, f: &mut Formatter) -> FmtResult {
896        write!(f, "{{")?;
897        for addr in self.bonded_addresses().iter() {
898            write!(f, "{:?}, ", addr)?;
899        }
900        write!(f, "}}")
901    }
902}
903
904fn to_gap_bonded_devices(bytes: &[u8]) -> Result<GapBondedDevices, crate::event::Error> {
905    let status = to_status(bytes)?;
906    match status {
907        crate::Status::Success => {
908            const HEADER_LEN: usize = 2;
909            const ADDR_LEN: usize = 7;
910
911            require_len_at_least!(bytes, HEADER_LEN);
912            let address_count = bytes[1] as usize;
913            if bytes.len() != HEADER_LEN + ADDR_LEN * address_count {
914                return Err(crate::event::Error::Vendor(
915                    super::VendorError::PartialBondedDeviceAddress,
916                ));
917            }
918
919            let mut address_buffer =
920                [crate::BdAddrType::Public(crate::BdAddr([0; 6])); MAX_ADDRESSES];
921            for (i, byte) in address_buffer.iter_mut().enumerate().take(address_count) {
922                let index = HEADER_LEN + i * ADDR_LEN;
923                let mut addr = [0; 6];
924                addr.copy_from_slice(&bytes[(1 + index)..(7 + index)]);
925                *byte = crate::to_bd_addr_type(bytes[index], crate::BdAddr(addr)).map_err(|e| {
926                    crate::event::Error::Vendor(super::VendorError::BadBdAddrType(e.0))
927                })?;
928            }
929
930            Ok(GapBondedDevices {
931                status,
932                address_count,
933                address_buffer,
934            })
935        }
936        _ => Ok(GapBondedDevices {
937            status,
938            address_count: 0,
939            address_buffer: [crate::BdAddrType::Public(crate::BdAddr([0; 6])); MAX_ADDRESSES],
940        }),
941    }
942}
943
944/// Parameters returned by the [GATT Add Service](crate::vendor::command::gatt::GattCommands::add_service) and
945/// [GATT Include Service](crate::vendor::command::gatt::GattCommands::include_service) commands.
946#[derive(Copy, Clone, Debug)]
947#[cfg_attr(feature = "defmt", derive(defmt::Format))]
948pub struct GattService {
949    /// Did the command fail, and if so, how?
950    pub status: crate::Status,
951
952    /// Handle of the Service
953    ///
954    /// When this service is added to the server, a handle is allocated by the server to this
955    /// service. Also server allocates a range of handles for this service from `service_handle` to
956    /// `service_handle +
957    /// [max_attribute_records](crate::vendor::command::gatt::AddServiceParameters::max_attribute_records)`.
958    pub service_handle: AttributeHandle,
959}
960
961fn to_gatt_service(bytes: &[u8]) -> Result<GattService, crate::event::Error> {
962    require_len!(bytes, 3);
963
964    Ok(GattService {
965        status: to_status(bytes)?,
966        service_handle: AttributeHandle(LittleEndian::read_u16(&bytes[1..3])),
967    })
968}
969
970/// Parameters returned by the [GATT Add Characteristic](crate::vendor::command::gatt::GattCommands::add_characteristic)
971/// command.
972#[derive(Copy, Clone, Debug)]
973#[cfg_attr(feature = "defmt", derive(defmt::Format))]
974pub struct GattCharacteristic {
975    /// Did the command fail, and if so, how?
976    pub status: crate::Status,
977
978    /// Handle of the characteristic.
979    pub characteristic_handle: AttributeHandle,
980}
981
982fn to_gatt_characteristic(bytes: &[u8]) -> Result<GattCharacteristic, crate::event::Error> {
983    require_len!(bytes, 3);
984
985    Ok(GattCharacteristic {
986        status: to_status(bytes)?,
987        characteristic_handle: AttributeHandle(LittleEndian::read_u16(&bytes[1..3])),
988    })
989}
990
991/// Parameters returned by the
992/// [GATT Add Characteristic Descriptor](crate::vendor::command::gatt::GattCommands::add_characteristic_descriptor) command.
993#[derive(Copy, Clone, Debug)]
994#[cfg_attr(feature = "defmt", derive(defmt::Format))]
995pub struct GattCharacteristicDescriptor {
996    /// Did the command fail, and if so, how?
997    pub status: crate::Status,
998
999    /// Handle of the characteristic.
1000    pub descriptor_handle: AttributeHandle,
1001}
1002
1003fn to_gatt_characteristic_descriptor(
1004    bytes: &[u8],
1005) -> Result<GattCharacteristicDescriptor, crate::event::Error> {
1006    require_len!(bytes, 3);
1007
1008    Ok(GattCharacteristicDescriptor {
1009        status: to_status(bytes)?,
1010        descriptor_handle: AttributeHandle(LittleEndian::read_u16(&bytes[1..3])),
1011    })
1012}
1013
1014/// Parameters returned by the [GATT Read Handle Value](crate::vendor::command::gatt::GattCommands::read_handle_value)
1015/// command.
1016#[derive(Copy, Clone)]
1017#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1018pub struct GattHandleValue {
1019    /// Did the command fail, and if so, how?
1020    pub status: crate::Status,
1021
1022    value_buf: [u8; GattHandleValue::MAX_VALUE_BUF],
1023    value_len: usize,
1024}
1025
1026impl Debug for GattHandleValue {
1027    fn fmt(&self, f: &mut Formatter) -> FmtResult {
1028        write!(f, "{{")?;
1029        write!(f, "status: {:?}; value: {{", self.status)?;
1030        for addr in self.value().iter() {
1031            write!(f, "{:?}, ", addr)?;
1032        }
1033        write!(f, "}}}}")
1034    }
1035}
1036
1037impl GattHandleValue {
1038    // Maximum length of the handle value. The spec says the length can be 2 bytes (up to 65535),
1039    // but the communication layer is limited to 255 bytes in a packet. There are 6 bytes reserved
1040    // for data other than the value, so the maximum length of the value buffer is 249 bytes.
1041    const MAX_VALUE_BUF: usize = 249;
1042
1043    /// Return the handle value. Only valid bytes are returned.
1044    pub fn value(&self) -> &[u8] {
1045        &self.value_buf[..self.value_len]
1046    }
1047}
1048
1049fn to_gatt_handle_value(bytes: &[u8]) -> Result<GattHandleValue, crate::event::Error> {
1050    require_len_at_least!(bytes, 3);
1051
1052    let status = to_status(bytes)?;
1053    let value_len = LittleEndian::read_u16(&bytes[1..3]) as usize;
1054    require_len!(bytes, 3 + value_len);
1055
1056    let mut handle_value = GattHandleValue {
1057        status,
1058        value_buf: [0; GattHandleValue::MAX_VALUE_BUF],
1059        value_len,
1060    };
1061    handle_value.value_buf[..value_len].copy_from_slice(&bytes[3..]);
1062
1063    Ok(handle_value)
1064}