1pub mod command;
8
9use byteorder::{ByteOrder, LittleEndian};
10use core::cmp::PartialEq;
11use core::convert::{TryFrom, TryInto};
12use core::fmt::{Debug, Formatter, Result as FmtResult};
13use core::mem;
14use core::time::Duration;
15
16use crate::host::PeerAddrType;
17pub use crate::types::{ConnectionInterval, ConnectionIntervalError};
18use crate::vendor::command::l2cap::L2CapCocReconfig;
19pub use crate::{BdAddr, BdAddrType, ConnectionHandle};
20
21#[allow(clippy::large_enum_variant)]
23#[derive(Clone, Copy, Debug)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum VendorEvent {
26 CoprocessorReady(FirmwareKind),
29
30 EventsLost(EventFlags),
34
35 GapLimitedDiscoverableTimeout,
43
44 GapPairingComplete(GapPairingComplete),
49
50 GapPassKeyRequest(ConnectionHandle),
54
55 GapAuthorizationRequest(ConnectionHandle),
60
61 GapPeripheralSecurityInitiated,
64
65 GapBondLost,
74
75 GapDeviceFound(GapDeviceFound),
78
79 GapProcedureComplete(GapProcedureComplete),
82
83 GapAddressNotResolved(ConnectionHandle),
87
88 GapNumericComparisonValue(GapNumericComparisonValue),
95
96 GapKeypressNotification(GapKeypressNotification),
101
102 L2CapConnectionUpdateResponse(L2CapConnectionUpdateResponse),
107
108 L2CapProcedureTimeout(ConnectionHandle),
111
112 L2CapConnectionUpdateRequest(L2CapConnectionUpdateRequest),
116
117 L2CapCommandReject(L2CapCommandReject),
121
122 L2CapCocConnect(L2CapCocConnect),
126
127 L2CapCocConnectConfirm(L2CapCocConnectConfirm),
131
132 L2CapCocReconfig(L2CapCocReconfig),
136
137 L2CapCocReconfigConfirm(L2CapCocReconfigConfirm),
141
142 L2CapCocDisconnect(u8),
149
150 L2CapCocFlowControl(L2CapCocFlowControl),
154
155 L2CapCocRxData(L2CapCocRxData),
164
165 L2CapCocTxPoolAvailable,
169
170 GattAttributeModified(GattAttributeModified),
178
179 GattProcedureTimeout(ConnectionHandle),
182
183 AttExchangeMtuResponse(AttExchangeMtuResponse),
185
186 AttFindInformationResponse(AttFindInformationResponse),
189
190 AttFindByTypeValueResponse(AttFindByTypeValueResponse),
192
193 AttReadByTypeResponse(AttReadByTypeResponse),
195
196 AttReadResponse(AttReadResponse),
198
199 AttReadBlobResponse(AttReadResponse),
203
204 AttReadMultipleResponse(AttReadResponse),
208
209 AttReadByGroupTypeResponse(AttReadByGroupTypeResponse),
212
213 AttPrepareWriteResponse(AttPrepareWriteResponse),
216
217 AttExecuteWriteResponse(ConnectionHandle),
220
221 GattIndication(AttributeValue),
223
224 GattNotification(AttributeValue),
226
227 GattProcedureComplete(GattProcedureComplete),
230
231 AttErrorResponse(AttErrorResponse),
236
237 GattDiscoverOrReadCharacteristicByUuidResponse(AttributeValue),
246
247 AttWritePermitRequest(AttributeValue),
259
260 AttReadPermitRequest(AttReadPermitRequest),
269
270 AttReadMultiplePermitRequest(AttReadMultiplePermitRequest),
279
280 GattTxPoolAvailable(GattTxPoolAvailable),
285
286 GattServerConfirmation(ConnectionHandle),
288
289 AttPrepareWritePermitRequest(AttPrepareWritePermitRequest),
299
300 GattEattBrearer(GattEattBrearer),
303
304 GattMultiNotification(GattMultiNotification),
306
307 GattNotificationComplete(AttributeHandle),
312
313 GattReadExt(GattReadExt),
322
323 GattIndicationExt(AttributeValueExt),
330
331 GattNotificationExt(AttributeValueExt),
338
339 HalEndOfRadioActivity(HalEndOfRadioActivity),
354
355 HalScanReqReport(HalScanReqReport),
360
361 HalFirmwareError(HalFirmwareError),
363}
364
365#[derive(Copy, Clone, Debug, PartialEq)]
367#[repr(u8)]
368#[cfg_attr(feature = "defmt", derive(defmt::Format))]
369pub enum VendorStatus {
370 Failed = 0x41,
372 InvalidParameters = 0x42,
374 NotAllowed = 0x46,
377 Error = 0x47,
379 AddressNotResolved = 0x48,
381 FlashReadFailed = 0x49,
383 FlashWriteFailed = 0x4A,
385 FlashEraseFailed = 0x4B,
387 InvalidCid = 0x50,
389 TimerNotValidLayer = 0x54,
391 TimerInsufficientResources = 0x55,
393 CsrkNotFound = 0x5A,
395 IrkNotFound = 0x5B,
397 DeviceNotFoundInDatabase = 0x5C,
399 SecurityDatabaseFull = 0x5D,
401 DeviceNotBonded = 0x5E,
403 DeviceInBlacklist = 0x5F,
405 InvalidHandle = 0x60,
407 InvalidParameter = 0x61,
409 OutOfHandle = 0x62,
411 InvalidOperation = 0x63,
413 InsufficientResources = 0x64,
415 InsufficientEncryptionKeySize = 0x65,
417 CharacteristicAlreadyExists = 0x66,
419 NoValidSlot = 0x82,
422 ScanWindowTooShort = 0x83,
425 NewIntervalFailed = 0x84,
429 IntervalTooLarge = 0x85,
433 LengthFailed = 0x86,
437 Timeout = 0xFF,
439 ProfileAlreadyInitialized = 0xF0,
441 NullParameter = 0xF1,
443}
444
445impl TryFrom<u8> for VendorStatus {
446 type Error = crate::BadStatusError;
447
448 fn try_from(value: u8) -> Result<Self, <Self as TryFrom<u8>>::Error> {
449 match value {
450 0x41 => Ok(VendorStatus::Failed),
451 0x42 => Ok(VendorStatus::InvalidParameters),
452 0x46 => Ok(VendorStatus::NotAllowed),
453 0x47 => Ok(VendorStatus::Error),
454 0x48 => Ok(VendorStatus::AddressNotResolved),
455 0x49 => Ok(VendorStatus::FlashReadFailed),
456 0x4A => Ok(VendorStatus::FlashWriteFailed),
457 0x4B => Ok(VendorStatus::FlashEraseFailed),
458 0x50 => Ok(VendorStatus::InvalidCid),
459 0x54 => Ok(VendorStatus::TimerNotValidLayer),
460 0x55 => Ok(VendorStatus::TimerInsufficientResources),
461 0x5A => Ok(VendorStatus::CsrkNotFound),
462 0x5B => Ok(VendorStatus::IrkNotFound),
463 0x5C => Ok(VendorStatus::DeviceNotFoundInDatabase),
464 0x5D => Ok(VendorStatus::SecurityDatabaseFull),
465 0x5E => Ok(VendorStatus::DeviceNotBonded),
466 0x5F => Ok(VendorStatus::DeviceInBlacklist),
467 0x60 => Ok(VendorStatus::InvalidHandle),
468 0x61 => Ok(VendorStatus::InvalidParameter),
469 0x62 => Ok(VendorStatus::OutOfHandle),
470 0x63 => Ok(VendorStatus::InvalidOperation),
471 0x64 => Ok(VendorStatus::InsufficientResources),
472 0x65 => Ok(VendorStatus::InsufficientEncryptionKeySize),
473 0x66 => Ok(VendorStatus::CharacteristicAlreadyExists),
474 0x82 => Ok(VendorStatus::NoValidSlot),
475 0x83 => Ok(VendorStatus::ScanWindowTooShort),
476 0x84 => Ok(VendorStatus::NewIntervalFailed),
477 0x85 => Ok(VendorStatus::IntervalTooLarge),
478 0x86 => Ok(VendorStatus::LengthFailed),
479 0xFF => Ok(VendorStatus::Timeout),
480 0xF0 => Ok(VendorStatus::ProfileAlreadyInitialized),
481 0xF1 => Ok(VendorStatus::NullParameter),
482 _ => Err(crate::BadStatusError::BadValue(value)),
483 }
484 }
485}
486
487impl From<VendorStatus> for u8 {
488 fn from(val: VendorStatus) -> Self {
489 val as u8
490 }
491}
492
493#[derive(Clone, Copy, Debug, PartialEq)]
495#[cfg_attr(feature = "defmt", derive(defmt::Format))]
496pub enum VendorError {
497 UnknownEvent(u16),
499
500 UnknownFirmwareKind(u8),
503
504 BadGapPairingStatus(u8),
507
508 BadGapPairingErrorReason(u8),
511
512 BadGapDeviceFoundEvent(u8),
515
516 BadGapBdAddrType(u8),
519
520 BadGapProcedure(u8),
523
524 BadGapProcedureStatus(u8),
527
528 BadL2CapDataLength(u8, u8),
531
532 BadL2CapLength(u16, u16),
535
536 BadL2CapRejectionReason(u16),
539
540 BadL2CapConnectionResponseCode(u8),
543
544 BadL2CapConnectionResponseResult(u16),
548
549 BadConnectionInterval(ConnectionIntervalError),
552
553 BadL2CapConnectionUpdateRequestInterval(Duration, Duration),
563
564 BadL2CapConnectionUpdateRequestLatency(u16, u16),
575
576 BadL2CapConnectionUpdateRequestTimeout(Duration),
584
585 BadAttFindInformationResponseFormat(u8),
588
589 AttFindInformationResponsePartialPair16,
592
593 AttFindInformationResponsePartialPair128,
596
597 AttFindByTypeValuePartial,
600
601 AttReadByTypeResponsePartial,
604
605 AttReadByGroupTypeResponsePartial,
608
609 BadGattProcedureStatus(u8),
612
613 BadAttRequestOpcode(u8),
616
617 BadAttError(u8),
620
621 AttReadMultiplePermitRequestPartial,
624
625 BadConfigParameterLength(usize),
630
631 UnknownLinkState(u8),
635
636 BadBooleanValue(u8),
643
644 BadPassKeyRequirement(u8),
648
649 PartialBondedDeviceAddress,
653
654 BadBdAddrType(u8),
658
659 BadEabState(u8),
661
662 BadRadioEvent(u8),
664
665 BadFirmwareError(u8),
667}
668
669macro_rules! require_len {
670 ($left:expr, $right:expr) => {
671 if $left.len() != $right {
672 return Err(crate::event::Error::BadLength($left.len(), $right));
673 }
674 };
675}
676
677macro_rules! require_len_at_least {
678 ($left:expr, $right:expr) => {
679 if $left.len() < $right {
680 return Err(crate::event::Error::BadLength($left.len(), $right));
681 }
682 };
683}
684
685fn first_16<T>(buffer: &[T]) -> &[T] {
686 if buffer.len() < 16 {
687 buffer
688 } else {
689 &buffer[..16]
690 }
691}
692
693impl VendorEvent {
694 pub fn new(buffer: &[u8]) -> Result<Self, crate::event::Error> {
695 require_len_at_least!(buffer, 2);
696
697 let event_code = LittleEndian::read_u16(&buffer[0..=1]);
698
699 match event_code {
700 0x9200 => Ok(VendorEvent::CoprocessorReady(to_coprocessor_ready(buffer)?)),
702
703 0x0004 => Ok(VendorEvent::HalEndOfRadioActivity(
704 to_hal_end_of_radio_activity(buffer)?,
705 )),
706 0x0005 => Ok(VendorEvent::HalScanReqReport(to_hal_scan_req_report(
707 buffer,
708 )?)),
709 0x0006 => Ok(VendorEvent::HalFirmwareError(to_hal_firmware_error(
710 buffer,
711 )?)),
712 0x0400 => Ok(VendorEvent::GapLimitedDiscoverableTimeout),
713 0x0401 => Ok(VendorEvent::GapPairingComplete(to_gap_pairing_complete(
714 buffer,
715 )?)),
716 0x0402 => Ok(VendorEvent::GapPassKeyRequest(to_conn_handle(buffer)?)),
717 0x0403 => Ok(VendorEvent::GapAuthorizationRequest(to_conn_handle(
718 buffer,
719 )?)),
720 0x0404 => Ok(VendorEvent::GapPeripheralSecurityInitiated),
721 0x0405 => Ok(VendorEvent::GapBondLost),
722 0x0406 => Ok(VendorEvent::GapDeviceFound(to_gap_device_found(buffer)?)),
723 0x0407 => Ok(VendorEvent::GapProcedureComplete(
724 to_gap_procedure_complete(buffer)?,
725 )),
726 0x0408 => Ok(VendorEvent::GapAddressNotResolved(to_conn_handle(buffer)?)),
727 0x0409 => Ok(VendorEvent::GapNumericComparisonValue(
728 to_numeric_comparison_value(buffer)?,
729 )),
730 0x040A => Ok(VendorEvent::GapKeypressNotification(
731 to_keypress_notification(buffer)?,
732 )),
733 0x0800 => Ok(VendorEvent::L2CapConnectionUpdateResponse(
734 to_l2cap_connection_update_response(buffer)?,
735 )),
736 0x0801 => Ok(VendorEvent::L2CapProcedureTimeout(
737 to_l2cap_procedure_timeout(buffer)?,
738 )),
739 0x0802 => Ok(VendorEvent::L2CapConnectionUpdateRequest(
740 to_l2cap_connection_update_request(buffer)?,
741 )),
742 0x080A => Ok(VendorEvent::L2CapCommandReject(to_l2cap_command_reject(
743 buffer,
744 )?)),
745 0x0810 => Ok(VendorEvent::L2CapCocConnect(to_l2cap_coc_connect(buffer)?)),
746 0x0811 => Ok(VendorEvent::L2CapCocConnectConfirm(
747 to_l2cap_coc_connect_confirm(buffer)?,
748 )),
749 0x0812 => Ok(VendorEvent::L2CapCocReconfig(to_l2cap_coc_reconfig(
750 buffer,
751 )?)),
752 0x0813 => Ok(VendorEvent::L2CapCocReconfigConfirm(
753 to_l2cap_coc_reconfig_confirm(buffer)?,
754 )),
755 0x0814 => Ok(VendorEvent::L2CapCocDisconnect({
756 require_len!(buffer, 1);
757 buffer[0]
758 })),
759 0x0815 => Ok(VendorEvent::L2CapCocFlowControl(to_l2cap_coc_flow_control(
760 buffer,
761 )?)),
762 0x0816 => Ok(VendorEvent::L2CapCocRxData(to_l2cap_coc_rx_data(buffer)?)),
763 0x0817 => Ok(VendorEvent::L2CapCocTxPoolAvailable),
764 0x0C01 => Ok(VendorEvent::GattAttributeModified(
765 to_gatt_attribute_modified(buffer)?,
766 )),
767 0x0C02 => Ok(VendorEvent::GattProcedureTimeout(to_conn_handle(buffer)?)),
768 0x0C03 => Ok(VendorEvent::AttExchangeMtuResponse(
769 to_att_exchange_mtu_resp(buffer)?,
770 )),
771 0x0C04 => Ok(VendorEvent::AttFindInformationResponse(
772 to_att_find_information_response(buffer)?,
773 )),
774 0x0C05 => Ok(VendorEvent::AttFindByTypeValueResponse(
775 to_att_find_by_value_type_response(buffer)?,
776 )),
777 0x0C06 => Ok(VendorEvent::AttReadByTypeResponse(
778 to_att_read_by_type_response(buffer)?,
779 )),
780 0x0C07 => Ok(VendorEvent::AttReadResponse(to_att_read_response(buffer)?)),
781 0x0C08 => Ok(VendorEvent::AttReadBlobResponse(to_att_read_response(
782 buffer,
783 )?)),
784 0x0C09 => Ok(VendorEvent::AttReadMultipleResponse(to_att_read_response(
785 buffer,
786 )?)),
787 0x0C0A => Ok(VendorEvent::AttReadByGroupTypeResponse(
788 to_att_read_by_group_type_response(buffer)?,
789 )),
790 0x0C0C => Ok(VendorEvent::AttPrepareWriteResponse(
791 to_att_prepare_write_response(buffer)?,
792 )),
793 0x0C0D => Ok(VendorEvent::AttExecuteWriteResponse(to_conn_handle(
794 buffer,
795 )?)),
796 0x0C0E => Ok(VendorEvent::GattIndication(to_attribute_value(buffer)?)),
797 0x0C0F => Ok(VendorEvent::GattNotification(to_attribute_value(buffer)?)),
798 0x0C10 => Ok(VendorEvent::GattProcedureComplete(
799 to_gatt_procedure_complete(buffer)?,
800 )),
801 0x0C11 => Ok(VendorEvent::AttErrorResponse(to_att_error_response(
802 buffer,
803 )?)),
804 0x0C12 => Ok(VendorEvent::GattDiscoverOrReadCharacteristicByUuidResponse(
805 to_attribute_value(buffer)?,
806 )),
807 0x0C13 => Ok(VendorEvent::AttWritePermitRequest(to_write_permit_request(
808 buffer,
809 )?)),
810 0x0C14 => Ok(VendorEvent::AttReadPermitRequest(
811 to_att_read_permit_request(buffer)?,
812 )),
813 0x0C15 => Ok(VendorEvent::AttReadMultiplePermitRequest(
814 to_att_read_multiple_permit_request(buffer)?,
815 )),
816 0x0C16 => Ok(VendorEvent::GattTxPoolAvailable(to_gatt_tx_pool_available(
817 buffer,
818 )?)),
819 0x0C17 => Ok(VendorEvent::GattServerConfirmation(to_conn_handle(buffer)?)),
820 0x0C18 => Ok(VendorEvent::AttPrepareWritePermitRequest(
821 to_att_prepare_write_permit_request(buffer)?,
822 )),
823 0x0C19 => Ok(VendorEvent::GattEattBrearer(to_gatt_eatt_bearer(buffer)?)),
824 0x0C1A => Ok(VendorEvent::GattMultiNotification(
825 to_gatt_multi_notification(buffer)?,
826 )),
827 0x0C1B => Ok(VendorEvent::GattNotificationComplete({
828 require_len!(buffer, 2);
829 AttributeHandle(LittleEndian::read_u16(buffer))
830 })),
831 0x0C1D => Ok(VendorEvent::GattReadExt(to_gatt_read_ext(buffer)?)),
832 0x0C1E => Ok(VendorEvent::GattIndicationExt(to_attribute_value_ext(
833 buffer,
834 )?)),
835 0x0C1F => Ok(VendorEvent::GattNotificationExt(to_attribute_value_ext(
836 buffer,
837 )?)),
838 _ => Err(crate::event::Error::Vendor(VendorError::UnknownEvent(
839 event_code,
840 ))),
841 }
842 }
843}
844
845#[derive(Clone, Copy, Debug, PartialEq)]
848#[cfg_attr(feature = "defmt", derive(defmt::Format))]
849pub enum FirmwareKind {
850 Wireless,
852
853 Rcc,
855}
856
857impl TryFrom<u8> for FirmwareKind {
858 type Error = VendorError;
859
860 fn try_from(value: u8) -> Result<Self, Self::Error> {
861 match value {
862 0 => Ok(FirmwareKind::Wireless),
863 1 => Ok(FirmwareKind::Rcc),
864 _ => Err(VendorError::UnknownFirmwareKind(value)),
865 }
866 }
867}
868
869fn to_coprocessor_ready(buffer: &[u8]) -> Result<FirmwareKind, crate::event::Error> {
876 require_len!(buffer, 3);
877
878 buffer[0].try_into().map_err(crate::event::Error::Vendor)
879}
880
881macro_rules! require_l2cap_event_data_len {
882 ($left:expr, $right:expr) => {
883 let actual = $left[4];
884 if actual != $right {
885 return Err(crate::event::Error::Vendor(
886 VendorError::BadL2CapDataLength(actual, $right),
887 ));
888 }
889 };
890}
891
892macro_rules! require_l2cap_len {
893 ($actual:expr, $expected:expr) => {
894 if $actual != $expected {
895 return Err(crate::event::Error::Vendor(VendorError::BadL2CapLength(
896 $actual, $expected,
897 )));
898 }
899 };
900}
901
902#[derive(Copy, Clone, Debug)]
908#[cfg_attr(feature = "defmt", derive(defmt::Format))]
909pub struct L2CapConnectionUpdateResponse {
910 pub conn_handle: ConnectionHandle,
912
913 pub result: L2CapConnectionUpdateResult,
915}
916
917#[derive(Copy, Clone, Debug, PartialEq)]
920#[cfg_attr(feature = "defmt", derive(defmt::Format))]
921pub enum L2CapRejectionReason {
922 CommandNotUnderstood,
924 SignalingMtuExceeded,
927 InvalidCid,
929}
930
931impl TryFrom<u16> for L2CapRejectionReason {
932 type Error = VendorError;
933
934 fn try_from(value: u16) -> Result<Self, Self::Error> {
935 match value {
936 0 => Ok(L2CapRejectionReason::CommandNotUnderstood),
937 1 => Ok(L2CapRejectionReason::SignalingMtuExceeded),
938 2 => Ok(L2CapRejectionReason::InvalidCid),
939 _ => Err(VendorError::BadL2CapRejectionReason(value)),
940 }
941 }
942}
943
944#[derive(Copy, Clone, Debug, PartialEq)]
946#[cfg_attr(feature = "defmt", derive(defmt::Format))]
947pub enum L2CapConnectionUpdateResult {
948 CommandRejected(L2CapRejectionReason),
950
951 ParametersRejected,
954
955 ParametersUpdated,
958}
959
960fn to_l2cap_connection_update_accepted_result(
961 value: u16,
962) -> Result<L2CapConnectionUpdateResult, VendorError> {
963 match value {
964 0x0000 => Ok(L2CapConnectionUpdateResult::ParametersUpdated),
965 0x0001 => Ok(L2CapConnectionUpdateResult::ParametersRejected),
966 _ => Err(VendorError::BadL2CapConnectionResponseResult(value)),
967 }
968}
969
970fn extract_l2cap_connection_update_response_result(
971 buffer: &[u8],
972) -> Result<L2CapConnectionUpdateResult, VendorError> {
973 match buffer[5] {
974 0x01 => Ok(L2CapConnectionUpdateResult::CommandRejected(
975 LittleEndian::read_u16(&buffer[9..]).try_into()?,
976 )),
977 0x13 => to_l2cap_connection_update_accepted_result(LittleEndian::read_u16(&buffer[9..])),
978 _ => Err(VendorError::BadL2CapConnectionResponseCode(buffer[5])),
979 }
980}
981
982fn to_l2cap_connection_update_response(
983 buffer: &[u8],
984) -> Result<L2CapConnectionUpdateResponse, crate::event::Error> {
985 require_len!(buffer, 11);
986 require_l2cap_event_data_len!(buffer, 6);
987 require_l2cap_len!(LittleEndian::read_u16(&buffer[7..]), 2);
988
989 Ok(L2CapConnectionUpdateResponse {
990 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
991 result: extract_l2cap_connection_update_response_result(buffer)
992 .map_err(crate::event::Error::Vendor)?,
993 })
994}
995
996#[derive(Copy, Clone, Debug)]
999#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1000pub struct L2CapProcedureTimeout {
1001 pub conn_handle: ConnectionHandle,
1003}
1004
1005fn to_l2cap_procedure_timeout(buffer: &[u8]) -> Result<ConnectionHandle, crate::event::Error> {
1006 require_len!(buffer, 5);
1007 require_l2cap_event_data_len!(buffer, 0);
1008
1009 Ok(ConnectionHandle(LittleEndian::read_u16(&buffer[2..])))
1010}
1011
1012#[derive(Copy, Clone, Debug)]
1020#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1021pub struct L2CapConnectionUpdateRequest {
1022 pub conn_handle: ConnectionHandle,
1027
1028 pub identifier: u8,
1033
1034 pub conn_interval: ConnectionInterval,
1036}
1037
1038fn to_l2cap_connection_update_request(
1039 buffer: &[u8],
1040) -> Result<L2CapConnectionUpdateRequest, crate::event::Error> {
1041 require_len!(buffer, 16);
1042 require_l2cap_event_data_len!(buffer, 11);
1043 require_l2cap_len!(LittleEndian::read_u16(&buffer[6..]), 8);
1044
1045 let interval = ConnectionInterval::from_bytes(&buffer[8..16])
1046 .map_err(VendorError::BadConnectionInterval)
1047 .map_err(crate::event::Error::Vendor)?;
1048
1049 Ok(L2CapConnectionUpdateRequest {
1050 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1051 identifier: buffer[5],
1052 conn_interval: interval,
1053 })
1054}
1055
1056#[derive(Copy, Clone, Debug)]
1061#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1062pub struct GapPairingComplete {
1063 pub conn_handle: ConnectionHandle,
1065
1066 pub status: GapPairingStatus,
1068
1069 pub reason: GapPairingReason,
1071}
1072
1073#[derive(Copy, Clone, Debug, PartialEq)]
1075#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1076pub enum GapPairingStatus {
1077 Success,
1079 Timeout,
1082 Failed,
1084}
1085
1086impl TryFrom<u8> for GapPairingStatus {
1087 type Error = VendorError;
1088
1089 fn try_from(value: u8) -> Result<Self, Self::Error> {
1090 match value {
1091 0 => Ok(GapPairingStatus::Success),
1092 1 => Ok(GapPairingStatus::Timeout),
1093 2 => Ok(GapPairingStatus::Failed),
1094 _ => Err(VendorError::BadGapPairingStatus(value)),
1095 }
1096 }
1097}
1098
1099#[derive(Copy, Clone, Debug, PartialEq)]
1101#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1102pub enum GapPairingReason {
1103 PasskeyEntryFailed = 0x01,
1104 OobNotAvailable = 0x02,
1105 AuthRequirements = 0x03,
1106 ConfirmValueFailed = 0x04,
1107 PairingNotSupported = 0x05,
1108 EncryptionKeySize = 0x06,
1109 CommandNotSupported = 0x07,
1110 Unspecified = 0x08,
1111 RepeatedAttemptes = 0x09,
1112 InvalidParams = 0x0A,
1113 DHKeyCheckFailed = 0x0B,
1114 NumericComparisonFailed = 0x0C,
1115 KeyRejected = 0x0F,
1116}
1117
1118impl TryFrom<u8> for GapPairingReason {
1119 type Error = VendorError;
1120
1121 fn try_from(value: u8) -> Result<Self, Self::Error> {
1122 match value {
1123 0x01 => Ok(GapPairingReason::PasskeyEntryFailed),
1124 0x02 => Ok(GapPairingReason::OobNotAvailable),
1125 0x03 => Ok(GapPairingReason::AuthRequirements),
1126 0x04 => Ok(GapPairingReason::ConfirmValueFailed),
1127 0x05 => Ok(GapPairingReason::PairingNotSupported),
1128 0x06 => Ok(GapPairingReason::EncryptionKeySize),
1129 0x07 => Ok(GapPairingReason::CommandNotSupported),
1130 0x08 => Ok(GapPairingReason::Unspecified),
1131 0x09 => Ok(GapPairingReason::RepeatedAttemptes),
1132 0x0A => Ok(GapPairingReason::InvalidParams),
1133 0x0B => Ok(GapPairingReason::DHKeyCheckFailed),
1134 0x0C => Ok(GapPairingReason::NumericComparisonFailed),
1135 0x0F => Ok(GapPairingReason::KeyRejected),
1136 _ => Err(VendorError::BadGapPairingErrorReason(value)),
1137 }
1138 }
1139}
1140
1141fn to_gap_pairing_complete(buffer: &[u8]) -> Result<GapPairingComplete, crate::event::Error> {
1142 require_len!(buffer, 6);
1143 Ok(GapPairingComplete {
1144 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1145 status: buffer[4].try_into().map_err(crate::event::Error::Vendor)?,
1146 reason: buffer[5].try_into().map_err(crate::event::Error::Vendor)?,
1147 })
1148}
1149
1150fn to_conn_handle(buffer: &[u8]) -> Result<ConnectionHandle, crate::event::Error> {
1151 require_len_at_least!(buffer, 4);
1152 Ok(ConnectionHandle(LittleEndian::read_u16(&buffer[2..])))
1153}
1154
1155#[derive(Copy, Clone, Debug)]
1158#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1159pub struct GapDeviceFound {
1160 pub event: GapDeviceFoundEvent,
1162
1163 pub bdaddr: BdAddrType,
1165
1166 data_len: usize,
1168
1169 data_buf: [u8; 31],
1171
1172 pub rssi: Option<i8>,
1174}
1175
1176impl GapDeviceFound {
1177 pub fn data(&self) -> &[u8] {
1179 &self.data_buf[..self.data_len]
1180 }
1181}
1182
1183pub use crate::event::AdvertisementEvent as GapDeviceFoundEvent;
1184
1185use super::command::gap::EventFlags;
1186use super::command::l2cap::{
1187 L2CapCocConnect, L2CapCocConnectConfirm, L2CapCocFlowControl, L2CapCocReconfigConfirm,
1188};
1189
1190fn to_gap_device_found(buffer: &[u8]) -> Result<GapDeviceFound, crate::event::Error> {
1191 const RSSI_UNAVAILABLE: i8 = 127;
1192
1193 require_len_at_least!(buffer, 12);
1194
1195 let data_len = buffer[10] as usize;
1196 require_len!(buffer, 12 + data_len);
1197
1198 let rssi = unsafe { mem::transmute::<u8, i8>(buffer[buffer.len() - 1]) };
1199
1200 let mut addr = BdAddr([0; 6]);
1201 addr.0.copy_from_slice(&buffer[4..10]);
1202 let mut event = GapDeviceFound {
1203 event: buffer[2].try_into().map_err(|e| {
1204 if let crate::event::Error::BadLeAdvertisementType(code) = e {
1205 crate::event::Error::Vendor(VendorError::BadGapDeviceFoundEvent(code))
1206 } else {
1207 unreachable!()
1208 }
1209 })?,
1210 bdaddr: crate::to_bd_addr_type(buffer[3], addr)
1211 .map_err(|e| crate::event::Error::Vendor(VendorError::BadGapBdAddrType(e.0)))?,
1212 data_len,
1213 data_buf: [0; 31],
1214 rssi: if rssi == RSSI_UNAVAILABLE {
1215 None
1216 } else {
1217 Some(rssi)
1218 },
1219 };
1220 event.data_buf[..event.data_len].copy_from_slice(&buffer[11..buffer.len() - 1]);
1221
1222 Ok(event)
1223}
1224
1225#[derive(Copy, Clone, Debug)]
1228#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1229pub struct GapProcedureComplete {
1230 pub procedure: GapProcedure,
1232 pub status: GapProcedureStatus,
1234}
1235
1236pub const MAX_NAME_LEN: usize = 248;
1239
1240#[derive(Copy, Clone)]
1243#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1244pub struct NameBuffer(pub [u8; MAX_NAME_LEN]);
1245
1246impl Debug for NameBuffer {
1247 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1248 first_16(&self.0).fmt(f)
1249 }
1250}
1251
1252impl PartialEq<NameBuffer> for NameBuffer {
1253 fn eq(&self, other: &Self) -> bool {
1254 if self.0.len() != other.0.len() {
1255 return false;
1256 }
1257
1258 for (a, b) in self.0.iter().zip(other.0.iter()) {
1259 if a != b {
1260 return false;
1261 }
1262 }
1263
1264 true
1265 }
1266}
1267
1268#[allow(clippy::large_enum_variant)]
1271#[derive(Copy, Clone, Debug, PartialEq)]
1272#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1273pub enum GapProcedure {
1274 LimitedDiscovery,
1276 GeneralDiscovery,
1278 NameDiscovery(usize, NameBuffer),
1281 AutoConnectionEstablishment,
1283 GeneralConnectionEstablishment,
1285 SelectiveConnectionEstablishment,
1287 DirectConnectionEstablishment,
1289 Observation,
1290}
1291
1292#[derive(Copy, Clone, Debug, PartialEq)]
1294#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1295pub enum GapProcedureStatus {
1296 Success,
1298 Failed,
1300 AuthFailure,
1302}
1303
1304impl TryFrom<u8> for GapProcedureStatus {
1305 type Error = VendorError;
1306
1307 fn try_from(value: u8) -> Result<Self, Self::Error> {
1308 match value {
1309 0x00 => Ok(GapProcedureStatus::Success),
1310 0x41 => Ok(GapProcedureStatus::Failed),
1311 0x05 => Ok(GapProcedureStatus::AuthFailure),
1312 _ => Err(VendorError::BadGapProcedureStatus(value)),
1313 }
1314 }
1315}
1316
1317fn to_gap_procedure_complete(buffer: &[u8]) -> Result<GapProcedureComplete, crate::event::Error> {
1318 require_len_at_least!(buffer, 4);
1319
1320 let procedure = match buffer[2] {
1321 0x01 => GapProcedure::LimitedDiscovery,
1322 0x02 => GapProcedure::GeneralDiscovery,
1323 0x04 => {
1324 require_len_at_least!(buffer, 5);
1325 let name_len = buffer.len() - 4;
1326 let mut name = NameBuffer([0; MAX_NAME_LEN]);
1327 name.0[..name_len].copy_from_slice(&buffer[4..]);
1328
1329 GapProcedure::NameDiscovery(name_len, name)
1330 }
1331 0x08 => GapProcedure::AutoConnectionEstablishment,
1332 0x10 => GapProcedure::GeneralConnectionEstablishment,
1333 0x20 => GapProcedure::SelectiveConnectionEstablishment,
1334 0x40 => GapProcedure::DirectConnectionEstablishment,
1335 0x80 => GapProcedure::Observation,
1336 _ => {
1337 return Err(crate::event::Error::Vendor(VendorError::BadGapProcedure(
1338 buffer[2],
1339 )));
1340 }
1341 };
1342
1343 Ok(GapProcedureComplete {
1344 procedure,
1345 status: buffer[3].try_into().map_err(crate::event::Error::Vendor)?,
1346 })
1347}
1348
1349#[derive(Copy, Clone)]
1357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1358pub struct GattAttributeModified {
1359 pub conn_handle: ConnectionHandle,
1361 pub attr_handle: AttributeHandle,
1363
1364 offset: u16,
1365
1366 data_len: usize,
1368 data_buf: [u8; MAX_ATTRIBUTE_LEN],
1371}
1372
1373impl GattAttributeModified {
1374 pub fn data(&self) -> &[u8] {
1377 &self.data_buf[..self.data_len]
1378 }
1379}
1380
1381#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1384#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1385pub struct AttributeHandle(pub u16);
1386
1387const MAX_ATTRIBUTE_LEN: usize = 248;
1390
1391impl Debug for GattAttributeModified {
1392 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1393 f.debug_struct("GattAttributeModified")
1394 .field("conn_handle", &self.conn_handle)
1395 .field("attr_handle", &self.attr_handle)
1396 .field("offset", &self.offset)
1397 .field("data", &first_16(self.data()))
1398 .finish()
1399 }
1400}
1401
1402fn to_gatt_attribute_modified(buffer: &[u8]) -> Result<GattAttributeModified, crate::event::Error> {
1403 require_len_at_least!(buffer, 10);
1404
1405 let data_len = LittleEndian::read_u16(&buffer[8..]) as usize;
1406 require_len!(buffer, 10 + data_len);
1407
1408 let mut data = [0; MAX_ATTRIBUTE_LEN];
1409 data[..data_len].copy_from_slice(&buffer[10..]);
1410
1411 let offset_field = LittleEndian::read_u16(&buffer[6..]);
1412 Ok(GattAttributeModified {
1413 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1414 attr_handle: AttributeHandle(LittleEndian::read_u16(&buffer[4..])),
1415 offset: (offset_field & 0x7FFF),
1416 data_len,
1417 data_buf: data,
1418 })
1419}
1420
1421#[derive(Copy, Clone, Debug)]
1423#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1424pub struct AttExchangeMtuResponse {
1425 pub conn_handle: ConnectionHandle,
1427
1428 pub server_rx_mtu: usize,
1430}
1431
1432fn to_att_exchange_mtu_resp(buffer: &[u8]) -> Result<AttExchangeMtuResponse, crate::event::Error> {
1433 require_len!(buffer, 6);
1434 Ok(AttExchangeMtuResponse {
1435 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1436 server_rx_mtu: LittleEndian::read_u16(&buffer[4..]) as usize,
1437 })
1438}
1439
1440#[derive(Copy, Clone, Debug)]
1443#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1444pub struct AttFindInformationResponse {
1445 pub conn_handle: ConnectionHandle,
1447 handle_uuid_pairs: HandleUuidPairs,
1452}
1453
1454impl AttFindInformationResponse {
1455 pub fn handle_uuid_pair_iter(&self) -> HandleUuidPairIterator {
1460 match self.handle_uuid_pairs {
1461 HandleUuidPairs::Format16(count, ref data) => {
1462 HandleUuidPairIterator::Format16(HandleUuid16PairIterator {
1463 data,
1464 count,
1465 next_index: 0,
1466 })
1467 }
1468 HandleUuidPairs::Format128(count, ref data) => {
1469 HandleUuidPairIterator::Format128(HandleUuid128PairIterator {
1470 data,
1471 count,
1472 next_index: 0,
1473 })
1474 }
1475 }
1476 }
1477}
1478
1479const MAX_FORMAT16_PAIR_COUNT: usize = 62;
1486const MAX_FORMAT128_PAIR_COUNT: usize = 13;
1487
1488#[derive(Copy, Clone, Debug)]
1491#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1492pub struct HandleUuid16Pair {
1493 pub handle: AttributeHandle,
1495 pub uuid: Uuid16,
1497}
1498
1499#[derive(Copy, Clone, Debug)]
1502#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1503pub struct HandleUuid128Pair {
1504 pub handle: AttributeHandle,
1506 pub uuid: Uuid128,
1508}
1509
1510#[derive(Copy, Clone, Debug, PartialEq)]
1512#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1513pub struct Uuid16(pub u16);
1514
1515#[derive(Copy, Clone, Debug, PartialEq)]
1517#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1518pub struct Uuid128(pub [u8; 16]);
1519
1520#[derive(Copy, Clone)]
1521#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1522enum HandleUuidPairs {
1523 Format16(usize, [HandleUuid16Pair; MAX_FORMAT16_PAIR_COUNT]),
1524 Format128(usize, [HandleUuid128Pair; MAX_FORMAT128_PAIR_COUNT]),
1525}
1526
1527impl Debug for HandleUuidPairs {
1528 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1529 write!(f, "{{")?;
1530 match *self {
1531 HandleUuidPairs::Format16(count, pairs) => {
1532 for handle_uuid_pair in &pairs[..count] {
1533 write!(
1534 f,
1535 "{{{:?}, {:?}}}",
1536 handle_uuid_pair.handle, handle_uuid_pair.uuid
1537 )?
1538 }
1539 }
1540 HandleUuidPairs::Format128(count, pairs) => {
1541 for handle_uuid_pair in &pairs[..count] {
1542 write!(
1543 f,
1544 "{{{:?}, {:?}}}",
1545 handle_uuid_pair.handle, handle_uuid_pair.uuid
1546 )?
1547 }
1548 }
1549 }
1550 write!(f, "}}")
1551 }
1552}
1553
1554#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1557pub enum HandleUuidPairIterator<'a> {
1558 Format16(HandleUuid16PairIterator<'a>),
1560 Format128(HandleUuid128PairIterator<'a>),
1562}
1563
1564#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1566pub struct HandleUuid16PairIterator<'a> {
1567 data: &'a [HandleUuid16Pair; MAX_FORMAT16_PAIR_COUNT],
1568 count: usize,
1569 next_index: usize,
1570}
1571
1572impl<'a> Iterator for HandleUuid16PairIterator<'a> {
1573 type Item = HandleUuid16Pair;
1574 fn next(&mut self) -> Option<Self::Item> {
1575 if self.next_index >= self.count {
1576 return None;
1577 }
1578
1579 let index = self.next_index;
1580 self.next_index += 1;
1581 Some(self.data[index])
1582 }
1583}
1584
1585#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1587pub struct HandleUuid128PairIterator<'a> {
1588 data: &'a [HandleUuid128Pair; MAX_FORMAT128_PAIR_COUNT],
1589 count: usize,
1590 next_index: usize,
1591}
1592
1593impl<'a> Iterator for HandleUuid128PairIterator<'a> {
1594 type Item = HandleUuid128Pair;
1595 fn next(&mut self) -> Option<Self::Item> {
1596 if self.next_index >= self.count {
1597 return None;
1598 }
1599
1600 let index = self.next_index;
1601 self.next_index += 1;
1602 Some(self.data[index])
1603 }
1604}
1605
1606fn to_att_find_information_response(
1607 buffer: &[u8],
1608) -> Result<AttFindInformationResponse, crate::event::Error> {
1609 require_len_at_least!(buffer, 4);
1610
1611 let data_len = buffer[5] as usize;
1612 require_len!(buffer, 6 + data_len);
1613
1614 Ok(AttFindInformationResponse {
1615 conn_handle: to_conn_handle(buffer)?,
1616 handle_uuid_pairs: match buffer[4] {
1617 1 => to_handle_uuid16_pairs(&buffer[6..]).map_err(crate::event::Error::Vendor)?,
1618 2 => to_handle_uuid128_pairs(&buffer[6..]).map_err(crate::event::Error::Vendor)?,
1619 _ => {
1620 return Err(crate::event::Error::Vendor(
1621 VendorError::BadAttFindInformationResponseFormat(buffer[4]),
1622 ));
1623 }
1624 },
1625 })
1626}
1627
1628fn to_handle_uuid16_pairs(buffer: &[u8]) -> Result<HandleUuidPairs, VendorError> {
1631 const PAIR_LEN: usize = 4;
1632 if buffer.len() % PAIR_LEN != 0 {
1633 return Err(VendorError::AttFindInformationResponsePartialPair16);
1634 }
1635
1636 let count = buffer.len() / PAIR_LEN;
1637 let mut pairs = [HandleUuid16Pair {
1638 handle: AttributeHandle(0),
1639 uuid: Uuid16(0),
1640 }; MAX_FORMAT16_PAIR_COUNT];
1641 for (i, pair) in pairs.iter_mut().enumerate().take(count) {
1642 let index = i * PAIR_LEN;
1643 pair.handle = AttributeHandle(LittleEndian::read_u16(&buffer[index..]));
1644 pair.uuid = Uuid16(LittleEndian::read_u16(&buffer[2 + index..]));
1645 }
1646
1647 Ok(HandleUuidPairs::Format16(count, pairs))
1648}
1649
1650fn to_handle_uuid128_pairs(buffer: &[u8]) -> Result<HandleUuidPairs, VendorError> {
1651 const PAIR_LEN: usize = 18;
1652 if buffer.len() % PAIR_LEN != 0 {
1653 return Err(VendorError::AttFindInformationResponsePartialPair128);
1654 }
1655
1656 let count = buffer.len() / PAIR_LEN;
1657 let mut pairs = [HandleUuid128Pair {
1658 handle: AttributeHandle(0),
1659 uuid: Uuid128([0; 16]),
1660 }; MAX_FORMAT128_PAIR_COUNT];
1661 for (i, pair) in pairs.iter_mut().enumerate().take(count) {
1662 let index = i * PAIR_LEN;
1663 let next_index = (i + 1) * PAIR_LEN;
1664 pair.handle = AttributeHandle(LittleEndian::read_u16(&buffer[index..]));
1665 pair.uuid.0.copy_from_slice(&buffer[2 + index..next_index]);
1666 }
1667
1668 Ok(HandleUuidPairs::Format128(count, pairs))
1669}
1670
1671#[derive(Copy, Clone)]
1673#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1674pub struct AttFindByTypeValueResponse {
1675 pub conn_handle: ConnectionHandle,
1677
1678 handle_pair_count: usize,
1680
1681 handles: [HandleInfoPair; MAX_HANDLE_INFO_PAIR_COUNT],
1683}
1684
1685impl AttFindByTypeValueResponse {
1686 pub fn handle_pairs_iter(&self) -> HandleInfoPairIterator {
1689 HandleInfoPairIterator {
1690 event: self,
1691 next_index: 0,
1692 }
1693 }
1694}
1695
1696impl Debug for AttFindByTypeValueResponse {
1697 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1698 write!(f, "{{.conn_handle = {:?}, ", self.conn_handle)?;
1699 for handle_pair in self.handle_pairs_iter() {
1700 write!(f, "{:?}", handle_pair)?;
1701 }
1702 write!(f, "}}")
1703 }
1704}
1705
1706const MAX_HANDLE_INFO_PAIR_COUNT: usize = 62;
1713
1714#[derive(Copy, Clone, Debug)]
1716#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1717pub struct HandleInfoPair {
1718 pub attribute: AttributeHandle,
1720 pub group_end: GroupEndHandle,
1722}
1723
1724#[derive(Copy, Clone, Debug, PartialEq)]
1726#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1727pub struct GroupEndHandle(pub u16);
1728
1729#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1732pub struct HandleInfoPairIterator<'a> {
1733 event: &'a AttFindByTypeValueResponse,
1734 next_index: usize,
1735}
1736
1737impl<'a> Iterator for HandleInfoPairIterator<'a> {
1738 type Item = HandleInfoPair;
1739
1740 fn next(&mut self) -> Option<Self::Item> {
1741 if self.next_index >= self.event.handle_pair_count {
1742 return None;
1743 }
1744
1745 let index = self.next_index;
1746 self.next_index += 1;
1747 Some(self.event.handles[index])
1748 }
1749}
1750
1751fn to_att_find_by_value_type_response(
1752 buffer: &[u8],
1753) -> Result<AttFindByTypeValueResponse, crate::event::Error> {
1754 const PAIR_LEN: usize = 4;
1755
1756 require_len_at_least!(buffer, 5);
1757
1758 let data_len = buffer[4] as usize;
1759 require_len!(buffer, 5 + data_len);
1760
1761 let pair_buffer = &buffer[5..];
1762 if pair_buffer.len() % PAIR_LEN != 0 {
1763 return Err(crate::event::Error::Vendor(
1764 VendorError::AttFindByTypeValuePartial,
1765 ));
1766 }
1767
1768 let count = pair_buffer.len() / PAIR_LEN;
1769 let mut pairs = [HandleInfoPair {
1770 attribute: AttributeHandle(0),
1771 group_end: GroupEndHandle(0),
1772 }; MAX_HANDLE_INFO_PAIR_COUNT];
1773 for (i, pair) in pairs.iter_mut().enumerate().take(count) {
1774 let index = i * PAIR_LEN;
1775 pair.attribute = AttributeHandle(LittleEndian::read_u16(&pair_buffer[index..]));
1776 pair.group_end = GroupEndHandle(LittleEndian::read_u16(&pair_buffer[2 + index..]));
1777 }
1778 Ok(AttFindByTypeValueResponse {
1779 conn_handle: to_conn_handle(buffer)?,
1780 handle_pair_count: count,
1781 handles: pairs,
1782 })
1783}
1784
1785#[derive(Copy, Clone)]
1787#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1788pub struct AttReadByTypeResponse {
1789 pub conn_handle: ConnectionHandle,
1791
1792 data_len: usize,
1794 value_len: usize,
1796 handle_value_pair_buf: [u8; MAX_HANDLE_VALUE_PAIR_BUF_LEN],
1799}
1800
1801const MAX_HANDLE_VALUE_PAIR_BUF_LEN: usize = 249;
1804
1805impl Debug for AttReadByTypeResponse {
1806 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1807 write!(f, "{{.conn_handle = {:?}, ", self.conn_handle)?;
1808 for handle_value_pair in self.handle_value_pair_iter() {
1809 write!(
1810 f,
1811 "{{handle: {:?}, value: {:?}}}",
1812 handle_value_pair.handle,
1813 first_16(handle_value_pair.value)
1814 )?;
1815 }
1816 write!(f, "}}")
1817 }
1818}
1819
1820impl AttReadByTypeResponse {
1821 pub fn handle_value_pair_iter(&self) -> HandleValuePairIterator {
1823 HandleValuePairIterator {
1824 event: self,
1825 index: 0,
1826 }
1827 }
1828}
1829
1830#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1833pub struct HandleValuePairIterator<'a> {
1834 event: &'a AttReadByTypeResponse,
1835 index: usize,
1836}
1837
1838impl<'a> Iterator for HandleValuePairIterator<'a> {
1839 type Item = HandleValuePair<'a>;
1840 fn next(&mut self) -> Option<Self::Item> {
1841 if self.index >= self.event.data_len {
1842 return None;
1843 }
1844
1845 let handle_index = self.index;
1846 let value_index = self.index + 2;
1847 self.index += 2 + self.event.value_len;
1848 let next_index = self.index;
1849 Some(HandleValuePair {
1850 handle: AttributeHandle(LittleEndian::read_u16(
1851 &self.event.handle_value_pair_buf[handle_index..],
1852 )),
1853 value: &self.event.handle_value_pair_buf[value_index..next_index],
1854 })
1855 }
1856}
1857
1858#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1860pub struct HandleValuePair<'a> {
1861 pub handle: AttributeHandle,
1863 pub value: &'a [u8],
1866}
1867
1868impl<'a> HandleValuePair<'a> {
1869 pub fn uuid(&self) -> u16 {
1870 LittleEndian::read_u16(&self.value[3..])
1871 }
1872}
1873
1874fn to_att_read_by_type_response(
1875 buffer: &[u8],
1876) -> Result<AttReadByTypeResponse, crate::event::Error> {
1877 require_len_at_least!(buffer, 6);
1878
1879 let data_len = buffer[5] as usize;
1880 require_len!(buffer, 6 + data_len);
1881
1882 let handle_value_pair_len = buffer[4] as usize;
1883 let handle_value_pair_buf = &buffer[6..];
1884 if handle_value_pair_buf.len() % handle_value_pair_len != 0 {
1885 return Err(crate::event::Error::Vendor(
1886 VendorError::AttReadByTypeResponsePartial,
1887 ));
1888 }
1889
1890 let mut full_handle_value_pair_buf = [0; MAX_HANDLE_VALUE_PAIR_BUF_LEN];
1891 full_handle_value_pair_buf[..handle_value_pair_buf.len()]
1892 .copy_from_slice(handle_value_pair_buf);
1893
1894 Ok(AttReadByTypeResponse {
1895 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1896 data_len: handle_value_pair_buf.len(),
1897 value_len: handle_value_pair_len - 2,
1898 handle_value_pair_buf: full_handle_value_pair_buf,
1899 })
1900}
1901
1902#[derive(Copy, Clone)]
1904#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1905pub struct AttReadResponse {
1906 pub conn_handle: ConnectionHandle,
1908
1909 value_len: usize,
1911
1912 value_buf: [u8; MAX_READ_RESPONSE_LEN],
1914}
1915
1916const MAX_READ_RESPONSE_LEN: usize = 250;
1919
1920impl Debug for AttReadResponse {
1921 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1922 write!(
1923 f,
1924 "{{.conn_handle = {:?}, value = {:?}}}",
1925 self.conn_handle,
1926 first_16(self.value())
1927 )
1928 }
1929}
1930
1931impl AttReadResponse {
1932 pub fn value(&self) -> &[u8] {
1934 &self.value_buf[..self.value_len]
1935 }
1936}
1937
1938fn to_att_read_response(buffer: &[u8]) -> Result<AttReadResponse, crate::event::Error> {
1939 require_len_at_least!(buffer, 5);
1940
1941 let data_len = buffer[4] as usize;
1942 require_len!(buffer, 5 + data_len);
1943
1944 let mut value_buf = [0; MAX_READ_RESPONSE_LEN];
1945 value_buf[..data_len].copy_from_slice(&buffer[5..]);
1946
1947 Ok(AttReadResponse {
1948 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
1949 value_len: data_len,
1950 value_buf,
1951 })
1952}
1953
1954#[derive(Copy, Clone)]
1957#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1958pub struct AttReadByGroupTypeResponse {
1959 pub conn_handle: ConnectionHandle,
1961
1962 attribute_group_len: usize,
1965
1966 data_len: usize,
1968
1969 attribute_data_buf: [u8; MAX_ATTRIBUTE_DATA_BUF_LEN],
1974}
1975
1976const MAX_ATTRIBUTE_DATA_BUF_LEN: usize = 249;
1979
1980impl AttReadByGroupTypeResponse {
1981 pub fn attribute_data_iter(&self) -> AttributeDataIterator {
1983 AttributeDataIterator {
1984 event: self,
1985 next_index: 0,
1986 }
1987 }
1988}
1989
1990impl Debug for AttReadByGroupTypeResponse {
1991 fn fmt(&self, f: &mut Formatter) -> FmtResult {
1992 write!(f, "{{.conn_handle = {:?}, ", self.conn_handle)?;
1993 for attribute_data in self.attribute_data_iter() {
1994 write!(
1995 f,
1996 "{{.attribute_handle = {:?}, .attribute_end_handle = {:?}, .value = {:?}}}",
1997 attribute_data.attribute_handle,
1998 attribute_data.attribute_end_handle,
1999 first_16(attribute_data.value)
2000 )?;
2001 }
2002 write!(f, "}}")
2003 }
2004}
2005
2006#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2008pub struct AttributeDataIterator<'a> {
2009 event: &'a AttReadByGroupTypeResponse,
2010 next_index: usize,
2011}
2012
2013impl<'a> Iterator for AttributeDataIterator<'a> {
2014 type Item = AttributeData<'a>;
2015 fn next(&mut self) -> Option<Self::Item> {
2016 if self.next_index >= self.event.data_len {
2017 return None;
2018 }
2019
2020 let attr_handle_index = self.next_index;
2021 let group_end_index = 2 + attr_handle_index;
2022 let value_index = 2 + group_end_index;
2023 self.next_index += self.event.attribute_group_len;
2024 Some(AttributeData {
2025 attribute_handle: AttributeHandle(LittleEndian::read_u16(
2026 &self.event.attribute_data_buf[attr_handle_index..],
2027 )),
2028 attribute_end_handle: AttributeHandle(LittleEndian::read_u16(
2029 &self.event.attribute_data_buf[group_end_index..],
2030 )),
2031 value: &self.event.attribute_data_buf[value_index..self.next_index],
2032 })
2033 }
2034}
2035
2036#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2038pub struct AttributeData<'a> {
2039 pub attribute_handle: AttributeHandle,
2041 pub attribute_end_handle: AttributeHandle,
2043 pub value: &'a [u8],
2045}
2046
2047impl<'a> AttributeData<'a> {
2048 pub fn uuid(&self) -> u16 {
2049 LittleEndian::read_u16(&self.value[0..])
2050 }
2051}
2052
2053fn to_att_read_by_group_type_response(
2054 buffer: &[u8],
2055) -> Result<AttReadByGroupTypeResponse, crate::event::Error> {
2056 require_len_at_least!(buffer, 6);
2057
2058 let data_len = buffer[5] as usize;
2059 require_len!(buffer, 6 + data_len);
2060
2061 let attribute_group_len = buffer[4] as usize;
2062
2063 if buffer[6..].len() % attribute_group_len != 0 {
2064 return Err(crate::event::Error::Vendor(
2065 VendorError::AttReadByGroupTypeResponsePartial,
2066 ));
2067 }
2068
2069 let mut attribute_data_buf = [0; MAX_ATTRIBUTE_DATA_BUF_LEN];
2070 attribute_data_buf[..data_len].copy_from_slice(&buffer[6..]);
2071 Ok(AttReadByGroupTypeResponse {
2072 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2073 data_len, attribute_group_len,
2075 attribute_data_buf,
2076 })
2077}
2078
2079#[derive(Copy, Clone)]
2082#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2083pub struct AttPrepareWriteResponse {
2084 pub conn_handle: ConnectionHandle,
2086 pub attribute_handle: AttributeHandle,
2088 pub offset: usize,
2090
2091 value_len: usize,
2093 value_buf: [u8; MAX_WRITE_RESPONSE_VALUE_LEN],
2094}
2095
2096const MAX_WRITE_RESPONSE_VALUE_LEN: usize = 246;
2099
2100impl Debug for AttPrepareWriteResponse {
2101 fn fmt(&self, f: &mut Formatter) -> FmtResult {
2102 write!(
2103 f,
2104 "{{.conn_handle = {:?}, .attribute_handle = {:?}, .offset = {}, .value = {:?}}}",
2105 self.conn_handle,
2106 self.attribute_handle,
2107 self.offset,
2108 first_16(self.value())
2109 )
2110 }
2111}
2112
2113impl AttPrepareWriteResponse {
2114 pub fn value(&self) -> &[u8] {
2116 &self.value_buf[..self.value_len]
2117 }
2118}
2119
2120fn to_att_prepare_write_response(
2121 buffer: &[u8],
2122) -> Result<AttPrepareWriteResponse, crate::event::Error> {
2123 require_len_at_least!(buffer, 9);
2124
2125 let data_len = buffer[4] as usize;
2126 require_len!(buffer, 5 + data_len);
2127
2128 let value_len = data_len - 4;
2129 let mut value_buf = [0; MAX_WRITE_RESPONSE_VALUE_LEN];
2130 value_buf[..value_len].copy_from_slice(&buffer[9..]);
2131 Ok(AttPrepareWriteResponse {
2132 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2133 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[5..])),
2134 offset: LittleEndian::read_u16(&buffer[7..]) as usize,
2135 value_len,
2136 value_buf,
2137 })
2138}
2139
2140#[derive(Copy, Clone)]
2143#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2144pub struct AttributeValue {
2145 pub conn_handle: ConnectionHandle,
2147 pub attribute_handle: AttributeHandle,
2149
2150 value_len: usize,
2152 value_buf: [u8; MAX_ATTRIBUTE_VALUE_LEN],
2154}
2155
2156const MAX_ATTRIBUTE_VALUE_LEN: usize = 248;
2159
2160impl Debug for AttributeValue {
2161 fn fmt(&self, f: &mut Formatter) -> FmtResult {
2162 write!(
2163 f,
2164 "{{.conn_handle = {:?}, .attribute_handle = {:?}, .value = {:?}}}",
2165 self.conn_handle,
2166 self.attribute_handle,
2167 first_16(self.value())
2168 )
2169 }
2170}
2171
2172impl AttributeValue {
2173 pub fn value(&self) -> &[u8] {
2175 &self.value_buf[..self.value_len]
2176 }
2177}
2178
2179fn to_attribute_value(buffer: &[u8]) -> Result<AttributeValue, crate::event::Error> {
2180 require_len_at_least!(buffer, 7);
2181
2182 let data_len = buffer[4] as usize;
2183 require_len!(buffer, 5 + data_len);
2184
2185 let value_len = data_len - 2;
2186 let mut value_buf = [0; MAX_ATTRIBUTE_VALUE_LEN];
2187 value_buf[..value_len].copy_from_slice(&buffer[7..]);
2188 Ok(AttributeValue {
2189 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2190 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[5..])),
2191 value_len,
2192 value_buf,
2193 })
2194}
2195
2196fn to_write_permit_request(buffer: &[u8]) -> Result<AttributeValue, crate::event::Error> {
2197 require_len_at_least!(buffer, 7);
2198
2199 let data_len = buffer[6] as usize;
2200 require_len!(buffer, 7 + data_len);
2201
2202 let value_len = data_len;
2203 let mut value_buf = [0; MAX_ATTRIBUTE_VALUE_LEN];
2204 value_buf[..value_len].copy_from_slice(&buffer[7..]);
2205 Ok(AttributeValue {
2206 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2207 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[4..])),
2208 value_len,
2209 value_buf,
2210 })
2211}
2212
2213#[derive(Copy, Clone, Debug)]
2216#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2217pub struct GattProcedureComplete {
2218 pub conn_handle: ConnectionHandle,
2220
2221 pub status: GattProcedureStatus,
2224}
2225
2226#[derive(Copy, Clone, Debug, PartialEq)]
2229#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2230pub enum GattProcedureStatus {
2231 Success,
2233 Failed,
2235}
2236
2237impl TryFrom<u8> for GattProcedureStatus {
2238 type Error = crate::event::Error;
2239
2240 fn try_from(value: u8) -> Result<Self, Self::Error> {
2241 match value {
2242 0x00 => Ok(GattProcedureStatus::Success),
2243 0x41 => Ok(GattProcedureStatus::Failed),
2244 _ => Err(crate::event::Error::Vendor(
2245 VendorError::BadGattProcedureStatus(value),
2246 )),
2247 }
2248 }
2249}
2250
2251fn to_gatt_procedure_complete(buffer: &[u8]) -> Result<GattProcedureComplete, crate::event::Error> {
2252 require_len!(buffer, 5);
2253
2254 Ok(GattProcedureComplete {
2255 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2256 status: buffer[4].try_into()?,
2257 })
2258}
2259
2260#[derive(Copy, Clone, Debug)]
2263#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2264pub struct AttErrorResponse {
2265 pub conn_handle: ConnectionHandle,
2267 pub request: AttRequest,
2269 pub attribute_handle: AttributeHandle,
2271 pub error: AttError,
2273}
2274
2275#[repr(u8)]
2279#[derive(Copy, Clone, Debug, PartialEq)]
2280#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2281pub enum AttError {
2282 InvalidHandle = 0x01,
2284 ReadNotPermitted = 0x02,
2286 WriteNotPermitted = 0x03,
2288 InvalidPdu = 0x04,
2290 InsufficientAuthentication = 0x05,
2292 RequestNotSupported = 0x06,
2294 InvalidOffset = 0x07,
2296 InsufficientAuthorization = 0x08,
2298 PrepareQueueFull = 0x09,
2300 AttributeNotFound = 0x0A,
2302 AttributeNotLong = 0x0B,
2304 InsufficientEncryptionKeySize = 0x0C,
2306 InvalidAttributeValueLength = 0x0D,
2308 UnlikelyError = 0x0E,
2311 InsufficientEncryption = 0x0F,
2313 UnsupportedGroupType = 0x10,
2316 InsufficientResources = 0x11,
2318 DatabaseOutOfSync = 0x12,
2320 ValueNotAllowed = 0x13,
2322 ApplicationError0x80 = 0x80,
2324 ApplicationError0x81 = 0x81,
2326 ApplicationError0x82 = 0x82,
2328 ApplicationError0x83 = 0x83,
2330 ApplicationError0x84 = 0x84,
2332 ApplicationError0x85 = 0x85,
2334 ApplicationError0x86 = 0x86,
2336 ApplicationError0x87 = 0x87,
2338 ApplicationError0x88 = 0x88,
2340 ApplicationError0x89 = 0x89,
2342 ApplicationError0x8A = 0x8A,
2344 ApplicationError0x8B = 0x8B,
2346 ApplicationError0x8C = 0x8C,
2348 ApplicationError0x8D = 0x8D,
2350 ApplicationError0x8E = 0x8E,
2352 ApplicationError0x8F = 0x8F,
2354 ApplicationError0x90 = 0x90,
2356 ApplicationError0x91 = 0x91,
2358 ApplicationError0x92 = 0x92,
2360 ApplicationError0x93 = 0x93,
2362 ApplicationError0x94 = 0x94,
2364 ApplicationError0x95 = 0x95,
2366 ApplicationError0x96 = 0x96,
2368 ApplicationError0x97 = 0x97,
2370 ApplicationError0x98 = 0x98,
2372 ApplicationError0x99 = 0x99,
2374 ApplicationError0x9A = 0x9A,
2376 ApplicationError0x9B = 0x9B,
2378 ApplicationError0x9C = 0x9C,
2380 ApplicationError0x9D = 0x9D,
2382 ApplicationError0x9E = 0x9E,
2384 ApplicationError0x9F = 0x9F,
2386 WriteRequestRejected = 0xFC,
2388 ClientCharacteristicConfigurationDescriptorImproperlyConfigured = 0xFD,
2391 ProcedureAlreadyInProgress = 0xFE,
2394 OutOfRange = 0xFF,
2396}
2397
2398impl TryFrom<u8> for AttError {
2399 type Error = u8;
2400
2401 fn try_from(value: u8) -> Result<Self, Self::Error> {
2402 match value {
2403 0x01 => Ok(AttError::InvalidHandle),
2404 0x02 => Ok(AttError::ReadNotPermitted),
2405 0x03 => Ok(AttError::WriteNotPermitted),
2406 0x04 => Ok(AttError::InvalidPdu),
2407 0x05 => Ok(AttError::InsufficientAuthentication),
2408 0x06 => Ok(AttError::RequestNotSupported),
2409 0x07 => Ok(AttError::InvalidOffset),
2410 0x08 => Ok(AttError::InsufficientAuthorization),
2411 0x09 => Ok(AttError::PrepareQueueFull),
2412 0x0A => Ok(AttError::AttributeNotFound),
2413 0x0B => Ok(AttError::AttributeNotLong),
2414 0x0C => Ok(AttError::InsufficientEncryptionKeySize),
2415 0x0D => Ok(AttError::InvalidAttributeValueLength),
2416 0x0E => Ok(AttError::UnlikelyError),
2417 0x0F => Ok(AttError::InsufficientEncryption),
2418 0x10 => Ok(AttError::UnsupportedGroupType),
2419 0x11 => Ok(AttError::InsufficientResources),
2420 0x80 => Ok(AttError::ApplicationError0x80),
2421 0x81 => Ok(AttError::ApplicationError0x81),
2422 0x82 => Ok(AttError::ApplicationError0x82),
2423 0x83 => Ok(AttError::ApplicationError0x83),
2424 0x84 => Ok(AttError::ApplicationError0x84),
2425 0x85 => Ok(AttError::ApplicationError0x85),
2426 0x86 => Ok(AttError::ApplicationError0x86),
2427 0x87 => Ok(AttError::ApplicationError0x87),
2428 0x88 => Ok(AttError::ApplicationError0x88),
2429 0x89 => Ok(AttError::ApplicationError0x89),
2430 0x8A => Ok(AttError::ApplicationError0x8A),
2431 0x8B => Ok(AttError::ApplicationError0x8B),
2432 0x8C => Ok(AttError::ApplicationError0x8C),
2433 0x8D => Ok(AttError::ApplicationError0x8D),
2434 0x8E => Ok(AttError::ApplicationError0x8E),
2435 0x8F => Ok(AttError::ApplicationError0x8F),
2436 0x90 => Ok(AttError::ApplicationError0x90),
2437 0x91 => Ok(AttError::ApplicationError0x91),
2438 0x92 => Ok(AttError::ApplicationError0x92),
2439 0x93 => Ok(AttError::ApplicationError0x93),
2440 0x94 => Ok(AttError::ApplicationError0x94),
2441 0x95 => Ok(AttError::ApplicationError0x95),
2442 0x96 => Ok(AttError::ApplicationError0x96),
2443 0x97 => Ok(AttError::ApplicationError0x97),
2444 0x98 => Ok(AttError::ApplicationError0x98),
2445 0x99 => Ok(AttError::ApplicationError0x99),
2446 0x9A => Ok(AttError::ApplicationError0x9A),
2447 0x9B => Ok(AttError::ApplicationError0x9B),
2448 0x9C => Ok(AttError::ApplicationError0x9C),
2449 0x9D => Ok(AttError::ApplicationError0x9D),
2450 0x9E => Ok(AttError::ApplicationError0x9E),
2451 0x9F => Ok(AttError::ApplicationError0x9F),
2452 0xFC => Ok(AttError::WriteRequestRejected),
2453 0xFD => Ok(AttError::ClientCharacteristicConfigurationDescriptorImproperlyConfigured),
2454 0xFE => Ok(AttError::ProcedureAlreadyInProgress),
2455 0xFF => Ok(AttError::OutOfRange),
2456 _ => Err(value),
2457 }
2458 }
2459}
2460
2461#[repr(u8)]
2464#[derive(Copy, Clone, Debug, PartialEq)]
2465#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2466pub enum AttRequest {
2467 ErrorResponse = 0x01,
2469 ExchangeMtuRequest = 0x02,
2471 ExchangeMtuResponse = 0x03,
2473 FindInformationRequest = 0x04,
2475 FindInformationResponse = 0x05,
2477 FindByTypeValueRequest = 0x06,
2479 FindByTypeValueResponse = 0x07,
2481 ReadByTypeRequest = 0x08,
2483 ReadByTypeResponse = 0x09,
2485 ReadRequest = 0x0A,
2487 ReadResponse = 0x0B,
2489 ReadBlobRequest = 0x0C,
2491 ReadBlobResponse = 0x0D,
2493 ReadMultipleRequest = 0x0E,
2495 ReadMultipleResponse = 0x0F,
2497 ReadByGroupTypeRequest = 0x10,
2499 ReadByGroupTypeResponse = 0x11,
2501 WriteRequest = 0x12,
2503 WriteResponse = 0x13,
2505 WriteCommand = 0x52,
2507 SignedWriteCommand = 0xD2,
2509 PrepareWriteRequest = 0x16,
2511 PrepareWriteResponse = 0x17,
2513 ExecuteWriteRequest = 0x18,
2515 ExecuteWriteResponse = 0x19,
2517 HandleValueNotification = 0x1B,
2519 HandleValueIndication = 0x1D,
2521 HandleValueConfirmation = 0x1E,
2523}
2524
2525impl TryFrom<u8> for AttRequest {
2526 type Error = VendorError;
2527
2528 fn try_from(value: u8) -> Result<Self, Self::Error> {
2529 match value {
2530 0x01 => Ok(AttRequest::ErrorResponse),
2531 0x02 => Ok(AttRequest::ExchangeMtuRequest),
2532 0x03 => Ok(AttRequest::ExchangeMtuResponse),
2533 0x04 => Ok(AttRequest::FindInformationRequest),
2534 0x05 => Ok(AttRequest::FindInformationResponse),
2535 0x06 => Ok(AttRequest::FindByTypeValueRequest),
2536 0x07 => Ok(AttRequest::FindByTypeValueResponse),
2537 0x08 => Ok(AttRequest::ReadByTypeRequest),
2538 0x09 => Ok(AttRequest::ReadByTypeResponse),
2539 0x0A => Ok(AttRequest::ReadRequest),
2540 0x0B => Ok(AttRequest::ReadResponse),
2541 0x0C => Ok(AttRequest::ReadBlobRequest),
2542 0x0D => Ok(AttRequest::ReadBlobResponse),
2543 0x0E => Ok(AttRequest::ReadMultipleRequest),
2544 0x0F => Ok(AttRequest::ReadMultipleResponse),
2545 0x10 => Ok(AttRequest::ReadByGroupTypeRequest),
2546 0x11 => Ok(AttRequest::ReadByGroupTypeResponse),
2547 0x12 => Ok(AttRequest::WriteRequest),
2548 0x13 => Ok(AttRequest::WriteResponse),
2549 0x52 => Ok(AttRequest::WriteCommand),
2550 0xD2 => Ok(AttRequest::SignedWriteCommand),
2551 0x16 => Ok(AttRequest::PrepareWriteRequest),
2552 0x17 => Ok(AttRequest::PrepareWriteResponse),
2553 0x18 => Ok(AttRequest::ExecuteWriteRequest),
2554 0x19 => Ok(AttRequest::ExecuteWriteResponse),
2555 0x1B => Ok(AttRequest::HandleValueNotification),
2556 0x1D => Ok(AttRequest::HandleValueIndication),
2557 0x1E => Ok(AttRequest::HandleValueConfirmation),
2558 _ => Err(VendorError::BadAttRequestOpcode(value)),
2559 }
2560 }
2561}
2562
2563fn to_att_error_response(buffer: &[u8]) -> Result<AttErrorResponse, crate::event::Error> {
2564 require_len!(buffer, 8);
2565 Ok(AttErrorResponse {
2566 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2567 request: buffer[4].try_into().map_err(crate::event::Error::Vendor)?,
2568 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[5..])),
2569 error: buffer[7]
2570 .try_into()
2571 .map_err(VendorError::BadAttError)
2572 .map_err(crate::event::Error::Vendor)?,
2573 })
2574}
2575
2576#[derive(Copy, Clone, Debug)]
2586#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2587pub struct AttReadPermitRequest {
2588 pub conn_handle: ConnectionHandle,
2590
2591 pub attribute_handle: AttributeHandle,
2593
2594 pub offset: usize,
2596}
2597
2598fn to_att_read_permit_request(buffer: &[u8]) -> Result<AttReadPermitRequest, crate::event::Error> {
2599 require_len!(buffer, 8);
2600 Ok(AttReadPermitRequest {
2601 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2602 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[4..])),
2603 offset: LittleEndian::read_u16(&buffer[6..]) as usize,
2604 })
2605}
2606
2607#[derive(Copy, Clone)]
2616#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2617pub struct AttReadMultiplePermitRequest {
2618 pub conn_handle: ConnectionHandle,
2620
2621 handles_len: usize,
2623 handles_buf: [AttributeHandle; MAX_ATTRIBUTE_HANDLE_BUFFER_LEN],
2626}
2627
2628const MAX_ATTRIBUTE_HANDLE_BUFFER_LEN: usize = 125;
2631
2632impl Debug for AttReadMultiplePermitRequest {
2633 fn fmt(&self, f: &mut Formatter) -> FmtResult {
2634 write!(
2635 f,
2636 "{{.conn_handle = {:?}, .handles = {:?}",
2637 self.conn_handle,
2638 first_16(self.handles())
2639 )
2640 }
2641}
2642
2643impl AttReadMultiplePermitRequest {
2644 pub fn handles(&self) -> &[AttributeHandle] {
2646 &self.handles_buf[..self.handles_len]
2647 }
2648}
2649
2650fn to_att_read_multiple_permit_request(
2651 buffer: &[u8],
2652) -> Result<AttReadMultiplePermitRequest, crate::event::Error> {
2653 require_len_at_least!(buffer, 5);
2654
2655 let data_len = buffer[4] as usize;
2656 if data_len % 2 != 0 {
2657 return Err(crate::event::Error::Vendor(
2658 VendorError::AttReadMultiplePermitRequestPartial,
2659 ));
2660 }
2661
2662 let handle_len = data_len / 2;
2663 let mut handles = [AttributeHandle(0); MAX_ATTRIBUTE_HANDLE_BUFFER_LEN];
2664 for (i, handle) in handles.iter_mut().enumerate().take(handle_len) {
2665 let index = 5 + 2 * i;
2666 *handle = AttributeHandle(LittleEndian::read_u16(&buffer[index..]));
2667 }
2668
2669 Ok(AttReadMultiplePermitRequest {
2670 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2671 handles_len: handle_len,
2672 handles_buf: handles,
2673 })
2674}
2675
2676#[derive(Copy, Clone, Debug)]
2680#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2681pub struct GattTxPoolAvailable {
2682 pub conn_handle: ConnectionHandle,
2684 pub available_buffers: usize,
2686}
2687
2688fn to_gatt_tx_pool_available(buffer: &[u8]) -> Result<GattTxPoolAvailable, crate::event::Error> {
2689 require_len!(buffer, 6);
2690 Ok(GattTxPoolAvailable {
2691 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2692 available_buffers: LittleEndian::read_u16(&buffer[4..]) as usize,
2693 })
2694}
2695
2696#[derive(Copy, Clone)]
2707#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2708pub struct AttPrepareWritePermitRequest {
2709 pub conn_handle: ConnectionHandle,
2711 pub attribute_handle: AttributeHandle,
2713 pub offset: usize,
2715
2716 value_len: usize,
2718 value_buf: [u8; MAX_PREPARE_WRITE_PERMIT_REQ_VALUE_LEN],
2720}
2721
2722const MAX_PREPARE_WRITE_PERMIT_REQ_VALUE_LEN: usize = 246;
2725
2726impl Debug for AttPrepareWritePermitRequest {
2727 fn fmt(&self, f: &mut Formatter) -> FmtResult {
2728 write!(
2729 f,
2730 "{{.conn_handle = {:?}, .attribute_handle = {:?}, .offset = {:?}, .value = {:?}",
2731 self.conn_handle,
2732 self.attribute_handle,
2733 self.offset,
2734 first_16(self.value())
2735 )
2736 }
2737}
2738
2739impl AttPrepareWritePermitRequest {
2740 pub fn value(&self) -> &[u8] {
2742 &self.value_buf[..self.value_len]
2743 }
2744}
2745
2746fn to_att_prepare_write_permit_request(
2747 buffer: &[u8],
2748) -> Result<AttPrepareWritePermitRequest, crate::event::Error> {
2749 require_len_at_least!(buffer, 9);
2750
2751 let data_len = buffer[8] as usize;
2752 require_len!(buffer, 9 + data_len);
2753
2754 let mut value_buf = [0; MAX_PREPARE_WRITE_PERMIT_REQ_VALUE_LEN];
2755 value_buf[..data_len].copy_from_slice(&buffer[9..]);
2756 Ok(AttPrepareWritePermitRequest {
2757 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2758 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[4..])),
2759 offset: LittleEndian::read_u16(&buffer[6..]) as usize,
2760 value_len: data_len,
2761 value_buf,
2762 })
2763}
2764
2765#[derive(Debug, Copy, Clone)]
2772#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2773pub struct GapNumericComparisonValue {
2774 pub connection_handle: ConnectionHandle,
2776 pub numeric_value: u32,
2778}
2779
2780fn to_numeric_comparison_value(
2781 buffer: &[u8],
2782) -> Result<GapNumericComparisonValue, crate::event::Error> {
2783 require_len!(buffer, 8);
2784
2785 Ok(GapNumericComparisonValue {
2786 connection_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[2..])),
2787 numeric_value: LittleEndian::read_u32(&buffer[4..]),
2788 })
2789}
2790
2791#[derive(Debug, Copy, Clone)]
2792#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2793pub struct GapKeypressNotification {
2798 pub connection_handle: ConnectionHandle,
2800 pub notification_type: KeypressNotificationType,
2803}
2804
2805#[derive(Debug, Copy, Clone)]
2806#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2807pub enum KeypressNotificationType {
2810 EntryStarted = 0x00,
2811 DigitEntered = 0x01,
2812 DigitErased = 0x02,
2813 PasskeyCleared = 0x03,
2814 EntryCompleted = 0x04,
2815 Reserved,
2816}
2817
2818impl From<u8> for KeypressNotificationType {
2819 fn from(value: u8) -> Self {
2820 match value {
2821 0x00 => KeypressNotificationType::EntryStarted,
2822 0x01 => KeypressNotificationType::DigitEntered,
2823 0x02 => KeypressNotificationType::DigitErased,
2824 0x03 => KeypressNotificationType::PasskeyCleared,
2825 0x04 => KeypressNotificationType::EntryCompleted,
2826 _ => KeypressNotificationType::Reserved,
2827 }
2828 }
2829}
2830
2831fn to_keypress_notification(buffer: &[u8]) -> Result<GapKeypressNotification, crate::event::Error> {
2832 require_len!(buffer, 3);
2833
2834 Ok(GapKeypressNotification {
2835 connection_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2836 notification_type: KeypressNotificationType::from(buffer[2]),
2837 })
2838}
2839
2840#[derive(Debug, Clone, Copy)]
2841#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2842pub struct L2CapCommandReject {
2846 pub conn_handle: ConnectionHandle,
2848 pub identifier: u8,
2850 pub reason: u16,
2852 pub data: [u8; 247],
2854}
2855
2856fn to_l2cap_command_reject(buffer: &[u8]) -> Result<L2CapCommandReject, crate::event::Error> {
2857 require_len_at_least!(buffer, 6);
2858
2859 let mut data = [0; 247];
2860 let len = buffer[5] as usize;
2861 data[..len].copy_from_slice(&buffer[6..(6 + len)]);
2862
2863 Ok(L2CapCommandReject {
2864 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2865 identifier: buffer[2],
2866 reason: LittleEndian::read_u16(&buffer[3..]),
2867 data,
2868 })
2869}
2870
2871fn to_l2cap_coc_connect(buffer: &[u8]) -> Result<L2CapCocConnect, crate::event::Error> {
2872 require_len!(buffer, 10);
2873
2874 Ok(L2CapCocConnect {
2875 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2876 spsm: LittleEndian::read_u16(&buffer[2..]),
2877 mtu: LittleEndian::read_u16(&buffer[4..]),
2878 mps: LittleEndian::read_u16(&buffer[6..]),
2879 initial_credits: LittleEndian::read_u16(&buffer[8..]),
2880 channel_number: buffer[10],
2881 })
2882}
2883
2884fn to_l2cap_coc_connect_confirm(
2885 buffer: &[u8],
2886) -> Result<L2CapCocConnectConfirm, crate::event::Error> {
2887 require_len!(buffer, 12);
2888
2889 let mut channel_index_list = [0; 246];
2890 let tmp = &buffer[7..];
2891 channel_index_list[..tmp.len()].copy_from_slice(tmp);
2892
2893 Ok(L2CapCocConnectConfirm {
2894 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2895 mtu: LittleEndian::read_u16(&buffer[4..]),
2896 mps: LittleEndian::read_u16(&buffer[6..]),
2897 initial_credits: LittleEndian::read_u16(&buffer[8..]),
2898 result: LittleEndian::read_u16(&buffer[10..]),
2899 channel_number: buffer[12],
2900 channel_index_list,
2901 })
2902}
2903
2904fn to_l2cap_coc_reconfig(buffer: &[u8]) -> Result<L2CapCocReconfig, crate::event::Error> {
2905 require_len_at_least!(buffer, 8);
2906
2907 let mut channel_index_list = [0; 246];
2908 let tmp = &buffer[7..];
2909 channel_index_list[..tmp.len()].copy_from_slice(tmp);
2910
2911 Ok(L2CapCocReconfig {
2912 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2913 mtu: LittleEndian::read_u16(&buffer[2..]),
2914 mps: LittleEndian::read_u16(&buffer[4..]),
2915 channel_number: buffer[6],
2916 channel_index_list,
2917 })
2918}
2919
2920fn to_l2cap_coc_reconfig_confirm(
2921 buffer: &[u8],
2922) -> Result<L2CapCocReconfigConfirm, crate::event::Error> {
2923 require_len_at_least!(buffer, 4);
2924
2925 Ok(L2CapCocReconfigConfirm {
2926 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
2927 result: LittleEndian::read_u16(&buffer[2..]),
2928 })
2929}
2930
2931fn to_l2cap_coc_flow_control(buffer: &[u8]) -> Result<L2CapCocFlowControl, crate::event::Error> {
2932 require_len!(buffer, 3);
2933
2934 Ok(L2CapCocFlowControl {
2935 channel_index: buffer[0],
2936 credits: LittleEndian::read_u16(&buffer[1..]),
2937 })
2938}
2939
2940#[derive(Debug, Clone, Copy)]
2941#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2942pub struct L2CapCocRxData {
2951 pub channel_index: u8,
2953 pub length: u16,
2955 pub data: [u8; 250],
2957}
2958
2959fn to_l2cap_coc_rx_data(buffer: &[u8]) -> Result<L2CapCocRxData, crate::event::Error> {
2960 require_len_at_least!(buffer, 3);
2961
2962 let length = LittleEndian::read_u16(&buffer[1..]);
2963 let mut data = [0; 250];
2964 data[..length as usize].copy_from_slice(&buffer[3..]);
2965
2966 Ok(L2CapCocRxData {
2967 channel_index: buffer[0],
2968 length,
2969 data,
2970 })
2971}
2972#[derive(Debug, Clone, Copy)]
2973#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2974pub struct GattEattBrearer {
2977 pub channel_index: u8,
2979 pub eab_state: EabState,
2981 pub status: GattProcedureStatus,
2983}
2984
2985#[derive(Debug, Clone, Copy)]
2986#[cfg_attr(feature = "defmt", derive(defmt::Format))]
2987pub enum EabState {
2989 AttBearerCreated = 0x00,
2990 AttBearerTerminated = 0x01,
2991}
2992
2993impl TryFrom<u8> for EabState {
2994 type Error = crate::event::Error;
2995
2996 fn try_from(value: u8) -> Result<Self, Self::Error> {
2997 match value {
2998 0x00 => Ok(EabState::AttBearerCreated),
2999 0x01 => Ok(EabState::AttBearerTerminated),
3000 err => Err(crate::event::Error::Vendor(VendorError::BadEabState(err))),
3001 }
3002 }
3003}
3004
3005fn to_gatt_eatt_bearer(buffer: &[u8]) -> Result<GattEattBrearer, crate::event::Error> {
3006 require_len!(buffer, 3);
3007
3008 Ok(GattEattBrearer {
3009 channel_index: buffer[0],
3010 eab_state: EabState::try_from(buffer[1])?,
3011 status: GattProcedureStatus::try_from(buffer[2])?,
3012 })
3013}
3014
3015#[derive(Debug, Clone, Copy)]
3016#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3017pub struct GattMultiNotification {
3019 pub conn_handle: ConnectionHandle,
3021 pub offset: u16,
3025 pub data_len: u16,
3027 pub data: [u8; 247],
3029}
3030
3031fn to_gatt_multi_notification(buffer: &[u8]) -> Result<GattMultiNotification, crate::event::Error> {
3032 require_len_at_least!(buffer, 6);
3033
3034 let data_len = LittleEndian::read_u16(&buffer[4..]);
3035 let mut data = [0; 247];
3036 data[..data_len as usize].copy_from_slice(&buffer[4..]);
3037
3038 Ok(GattMultiNotification {
3039 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
3040 offset: LittleEndian::read_u16(&buffer[2..]),
3041 data_len,
3042 data,
3043 })
3044}
3045
3046#[derive(Debug, Clone, Copy)]
3047#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3048pub struct GattReadExt {
3050 pub conn_handle: ConnectionHandle,
3052 pub offset: u16,
3057
3058 value_len: usize,
3060 value_buf: [u8; MAX_ATTRIBUTE_VALUE_LEN],
3062}
3063
3064fn to_gatt_read_ext(buffer: &[u8]) -> Result<GattReadExt, crate::event::Error> {
3065 require_len_at_least!(buffer, 6);
3066
3067 let value_len = LittleEndian::read_u16(&buffer[4..]) as usize;
3068 require_len!(buffer, 6 + value_len);
3069
3070 let mut value_buf = [0; MAX_ATTRIBUTE_VALUE_LEN];
3071 value_buf[..value_len].copy_from_slice(&buffer[6..]);
3072
3073 Ok(GattReadExt {
3074 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
3075 offset: LittleEndian::read_u16(&buffer[2..]),
3076 value_len,
3077 value_buf,
3078 })
3079}
3080
3081impl GattReadExt {
3082 pub fn value(&self) -> &[u8] {
3083 &self.value_buf[..self.value_len]
3084 }
3085}
3086
3087#[derive(Debug, Clone, Copy)]
3088#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3089pub struct AttributeValueExt {
3092 pub conn_handle: ConnectionHandle,
3094 pub attribute_handle: AttributeHandle,
3096 pub offset: u16,
3101
3102 value_len: usize,
3104 value_buf: [u8; MAX_ATTRIBUTE_VALUE_LEN],
3106}
3107
3108fn to_attribute_value_ext(buffer: &[u8]) -> Result<AttributeValueExt, crate::event::Error> {
3109 require_len_at_least!(buffer, 6);
3110
3111 let value_len = LittleEndian::read_u16(&buffer[6..]) as usize;
3112 require_len!(buffer, 8 + value_len);
3113
3114 let mut value_buf = [0; MAX_ATTRIBUTE_VALUE_LEN];
3115 value_buf[..value_len].copy_from_slice(&buffer[8..]);
3116
3117 Ok(AttributeValueExt {
3118 conn_handle: ConnectionHandle(LittleEndian::read_u16(&buffer[0..])),
3119 attribute_handle: AttributeHandle(LittleEndian::read_u16(&buffer[2..])),
3120 offset: LittleEndian::read_u16(&buffer[4..]),
3121 value_len,
3122 value_buf,
3123 })
3124}
3125
3126impl AttributeValueExt {
3127 pub fn value(&self) -> &[u8] {
3128 &self.value_buf[..self.value_len]
3129 }
3130}
3131
3132#[derive(Debug, Clone, Copy)]
3133#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3134pub struct HalEndOfRadioActivity {
3136 pub last_state: RadioEvent,
3138 pub next_state: RadioEvent,
3140 pub next_state_sys_time: u32,
3142 pub last_state_slot: u8,
3148 pub next_state_slot: u8,
3154}
3155
3156#[derive(Debug, Clone, Copy)]
3157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3158pub enum RadioEvent {
3159 Idle = 0x00,
3160 Advertising = 0x01,
3161 PeripheralConnection = 0x02,
3162 Scanning = 0x03,
3163 CentralConnection = 0x05,
3164 TxTestMode = 0x06,
3165 RxTestMode = 0x07,
3166}
3167
3168impl TryFrom<u8> for RadioEvent {
3169 type Error = crate::event::Error;
3170
3171 fn try_from(value: u8) -> Result<Self, Self::Error> {
3172 match value {
3173 0x00 => Ok(RadioEvent::Idle),
3174 0x01 => Ok(RadioEvent::Advertising),
3175 0x02 => Ok(RadioEvent::PeripheralConnection),
3176 0x03 => Ok(RadioEvent::Scanning),
3177 0x05 => Ok(RadioEvent::CentralConnection),
3178 0x06 => Ok(RadioEvent::TxTestMode),
3179 0x07 => Ok(RadioEvent::RxTestMode),
3180 x => Err(crate::event::Error::Vendor(VendorError::BadRadioEvent(x))),
3181 }
3182 }
3183}
3184
3185fn to_hal_end_of_radio_activity(
3186 buffer: &[u8],
3187) -> Result<HalEndOfRadioActivity, crate::event::Error> {
3188 require_len!(buffer, 7);
3189
3190 Ok(HalEndOfRadioActivity {
3191 last_state: RadioEvent::try_from(buffer[0])?,
3192 next_state: RadioEvent::try_from(buffer[1])?,
3193 next_state_sys_time: LittleEndian::read_u32(&buffer[2..]),
3194 last_state_slot: buffer[6],
3195 next_state_slot: buffer[7],
3196 })
3197}
3198
3199#[derive(Debug, Clone, Copy)]
3200#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3201pub struct HalScanReqReport {
3203 pub rssi: u8,
3211 pub peer_addr: PeerAddrType,
3213}
3214
3215fn to_hal_scan_req_report(buffer: &[u8]) -> Result<HalScanReqReport, crate::event::Error> {
3216 require_len!(buffer, 8);
3217
3218 let mut addr = crate::BdAddr([0; 6]);
3219 addr.0.copy_from_slice(&buffer[2..]);
3220
3221 Ok(HalScanReqReport {
3222 rssi: buffer[0],
3223 peer_addr: match buffer[1] {
3224 0x00 => PeerAddrType::PublicDeviceAddress(addr),
3225 0x01 => PeerAddrType::RandomDeviceAddress(addr),
3226 0x02 => PeerAddrType::PublicDeviceAddress(addr),
3227 0x03 => PeerAddrType::RandomIdentityAddress(addr),
3228 x => return Err(crate::event::Error::Vendor(VendorError::BadBdAddrType(x))),
3229 },
3230 })
3231}
3232
3233#[derive(Debug, Clone, Copy)]
3234#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3235pub struct HalFirmwareError {
3237 pub fw_error_type: FirmwareError,
3239 data_len: u8,
3241 data: [u8; 251],
3243}
3244
3245#[derive(Debug, Clone, Copy)]
3246#[cfg_attr(feature = "defmt", derive(defmt::Format))]
3247pub enum FirmwareError {
3249 L2capRecombination = 0x01,
3251 GattUnexpectedPeerMsg = 0x02,
3253 NvmLevelWarning = 0x03,
3255 CocRxDataTooLarge = 0x04,
3257}
3258
3259impl TryFrom<u8> for FirmwareError {
3260 type Error = crate::event::Error;
3261
3262 fn try_from(value: u8) -> Result<Self, Self::Error> {
3263 match value {
3264 0x01 => Ok(FirmwareError::L2capRecombination),
3265 0x02 => Ok(FirmwareError::GattUnexpectedPeerMsg),
3266 0x03 => Ok(FirmwareError::NvmLevelWarning),
3267 0x04 => Ok(FirmwareError::CocRxDataTooLarge),
3268 x => Err(crate::event::Error::Vendor(VendorError::BadFirmwareError(
3269 x,
3270 ))),
3271 }
3272 }
3273}
3274
3275impl HalFirmwareError {
3276 pub fn data(&self) -> &[u8] {
3277 &self.data[..self.data_len as usize]
3278 }
3279}
3280
3281fn to_hal_firmware_error(buffer: &[u8]) -> Result<HalFirmwareError, crate::event::Error> {
3282 require_len_at_least!(buffer, 2);
3283
3284 let data_len = buffer[1] as usize;
3285 let mut data = [0; 251];
3286 data[..data_len].copy_from_slice(&buffer[2..(2 + data_len)]);
3287
3288 Ok(HalFirmwareError {
3289 fw_error_type: FirmwareError::try_from(buffer[0])?,
3290 data_len: buffer[1],
3291 data,
3292 })
3293}