1use 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#[allow(clippy::large_enum_variant)]
19#[derive(Clone, Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub enum VendorReturnParameters {
22 HalGetFirmwareRevision(HalFirmwareRevision),
25
26 HalWriteConfigData(crate::Status),
29
30 HalReadConfigData(HalConfigData),
33
34 HalSetTxPowerLevel(crate::Status),
37
38 HalDeviceStandby(crate::Status),
41
42 HalGetTxTestPacketCount(HalTxTestPacketCount),
45
46 HalStartTone(crate::Status),
48
49 HalStopTone(crate::Status),
51
52 HalGetLinkStatus(HalLinkStatus),
54
55 HalGetAnchorPeriod(HalAnchorPeriod),
58
59 HalGetPmDebugInfo(HalPmDebugInfo),
62
63 HalReadRssi(u8),
66
67 HalReadRadioReg(u8),
70
71 HalReadRawRssi(u8),
74
75 GapSetNonDiscoverable(crate::Status),
79
80 GapSetDiscoverable(crate::Status),
84
85 GapSetDirectConnectable(crate::Status),
88
89 GapSetIoCapability(crate::Status),
92
93 GapSetAuthenticationRequirement(crate::Status),
96
97 GapSetAuthorizationRequirement(crate::Status),
100
101 GapPassKeyResponse(crate::Status),
105
106 GapAuthorizationResponse(crate::Status),
109
110 GapInit(GapInit),
112
113 GapSetNonConnectable(crate::Status),
116
117 GapSetUndirectedConnectable(crate::Status),
120
121 GapUpdateAdvertisingData(crate::Status),
124
125 GapDeleteAdType(crate::Status),
129
130 GapGetSecurityLevel(GapSecurityLevel),
133
134 GapSetEventMask(crate::Status),
138
139 GapConfigureWhiteList(crate::Status),
142
143 GapClearSecurityDatabase(crate::Status),
146
147 GapAllowRebond(crate::Status),
150
151 GapTerminateProcedure(crate::Status),
154
155 GapResolvePrivateAddress(GapResolvePrivateAddress),
158
159 GapGetBondedDevices(GapBondedDevices),
162
163 GapSetBroadcastMode(crate::Status),
166
167 GapStartObservationProcedure(crate::Status),
170
171 GapIsDeviceBonded(crate::Status),
175
176 GattInit(crate::Status),
179
180 GattAddService(GattService),
183
184 GattIncludeService(GattService),
188
189 GattAddCharacteristic(GattCharacteristic),
192
193 GattAddCharacteristicDescriptor(GattCharacteristicDescriptor),
196
197 GattUpdateCharacteristicValue(crate::Status),
200
201 GattDeleteCharacteristic(crate::Status),
204
205 GattDeleteService(crate::Status),
209
210 GattDeleteIncludedService(crate::Status),
213
214 GattSetEventMask(crate::Status),
217
218 GattWriteWithoutResponse(crate::Status),
221
222 GattSignedWriteWithoutResponse(crate::Status),
225
226 GattConfirmIndication(crate::Status),
229
230 GattWriteResponse(crate::Status),
233
234 GattAllowRead(crate::Status),
236
237 GattSetSecurityPermission(crate::Status),
240
241 GattSetDescriptorValue(crate::Status),
244
245 GattReadHandleValue(GattHandleValue),
248
249 GattReadHandleValueOffset(GattHandleValue),
252
253 GattUpdateLongCharacteristicValue(crate::Status),
256
257 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#[derive(Clone, Debug)]
484#[cfg_attr(feature = "defmt", derive(defmt::Format))]
485pub struct HalFirmwareRevision {
486 pub status: crate::Status,
488
489 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#[derive(Clone, Debug)]
505#[cfg_attr(feature = "defmt", derive(defmt::Format))]
506pub struct HalConfigData {
507 pub status: crate::Status,
509
510 pub value: HalConfigParameter,
519}
520
521#[derive(Clone, Debug, PartialEq)]
524#[cfg_attr(feature = "defmt", derive(defmt::Format))]
525pub enum HalConfigParameter {
526 PublicAddress(crate::BdAddr),
529
530 RandomAddress(crate::BdAddr),
533
534 Diversifier(u16),
537
538 EncryptionKey(crate::host::EncryptionKey),
542
543 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#[derive(Clone, Debug)]
586#[cfg_attr(feature = "defmt", derive(defmt::Format))]
587pub struct HalTxTestPacketCount {
588 pub status: crate::Status,
590
591 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#[derive(Clone, Debug)]
605#[cfg_attr(feature = "defmt", derive(defmt::Format))]
606pub struct HalLinkStatus {
607 pub status: crate::Status,
609
610 pub clients: [ClientStatus; 8],
612}
613
614#[derive(Copy, Clone, Debug, PartialEq)]
616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
617pub struct ClientStatus {
618 pub state: LinkState,
620
621 pub conn_handle: crate::ConnectionHandle,
623}
624
625#[derive(Copy, Clone, Debug, PartialEq)]
627#[cfg_attr(feature = "defmt", derive(defmt::Format))]
628pub enum LinkState {
629 Idle,
631 Advertising,
633 ConnectedAsPeripheral,
635 Scanning,
637 Reserved,
639 ConnectedAsPrimary,
641 TxTest,
643 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#[derive(Clone, Debug)]
691#[cfg_attr(feature = "defmt", derive(defmt::Format))]
692pub struct HalAnchorPeriod {
693 pub status: crate::Status,
695
696 pub anchor_interval: Duration,
698
699 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#[derive(Clone, Debug)]
718#[cfg_attr(feature = "defmt", derive(defmt::Format))]
719pub struct HalPmDebugInfo {
720 pub tx: u8,
722 pub rx: u8,
724 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#[derive(Copy, Clone, Debug)]
740#[cfg_attr(feature = "defmt", derive(defmt::Format))]
741pub struct GapInit {
742 pub status: crate::Status,
748
749 pub service_handle: AttributeHandle,
751
752 pub dev_name_handle: AttributeHandle,
754
755 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#[derive(Copy, Clone, Debug)]
773#[cfg_attr(feature = "defmt", derive(defmt::Format))]
774pub struct GapSecurityLevel {
775 pub status: crate::Status,
777
778 pub mitm_protection_required: bool,
780
781 pub bonding_required: bool,
783
784 pub out_of_band_data_present: bool,
786
787 pub pass_key_required: PassKeyRequirement,
789}
790
791#[derive(Copy, Clone, Debug, PartialEq)]
793#[cfg_attr(feature = "defmt", derive(defmt::Format))]
794pub enum PassKeyRequirement {
795 NotRequired,
797 FixedPin,
799 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#[derive(Copy, Clone, Debug)]
839#[cfg_attr(feature = "defmt", derive(defmt::Format))]
840pub struct GapResolvePrivateAddress {
841 pub status: crate::Status,
843
844 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#[derive(Copy, Clone)]
874#[cfg_attr(feature = "defmt", derive(defmt::Format))]
875pub struct GapBondedDevices {
876 pub status: crate::Status,
878
879 address_count: usize,
881 address_buffer: [crate::BdAddrType; MAX_ADDRESSES],
882}
883
884const MAX_ADDRESSES: usize = 35;
886
887impl GapBondedDevices {
888 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#[derive(Copy, Clone, Debug)]
947#[cfg_attr(feature = "defmt", derive(defmt::Format))]
948pub struct GattService {
949 pub status: crate::Status,
951
952 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#[derive(Copy, Clone, Debug)]
973#[cfg_attr(feature = "defmt", derive(defmt::Format))]
974pub struct GattCharacteristic {
975 pub status: crate::Status,
977
978 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#[derive(Copy, Clone, Debug)]
994#[cfg_attr(feature = "defmt", derive(defmt::Format))]
995pub struct GattCharacteristicDescriptor {
996 pub status: crate::Status,
998
999 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#[derive(Copy, Clone)]
1017#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1018pub struct GattHandleValue {
1019 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 const MAX_VALUE_BUF: usize = 249;
1042
1043 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}