1use bitflags::bitflags;
2use zerocopy::{FromBytes, Immutable, IntoBytes};
3
4#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub struct BstReturn {
8 pub battery_state: BatteryState,
10 pub battery_present_rate: u32,
15 pub battery_remaining_capacity: u32,
20 pub battery_present_voltage: u32,
25}
26
27pub const BST_RETURN_SIZE_BYTES: usize = 16;
29
30#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
32#[cfg_attr(feature = "defmt", derive(defmt::Format))]
33pub struct BatteryState(u32);
34bitflags! {
35 impl BatteryState: u32 {
36 const DISCHARGING = 1 << 0;
38
39 const CHARGING = 1 << 1;
41
42 const CRITICAL = 1 << 2;
44
45 const CHARGE_LIMITING = 1 << 3;
47 }
48}
49
50#[repr(C)]
55#[derive(Default, PartialEq, Eq, Immutable)]
56#[cfg_attr(feature = "defmt", derive(defmt::Format))]
57pub struct BixReturn<'a> {
58 pub revision: u32,
60 pub power_unit: PowerUnit,
62 pub design_capacity: u32,
64 pub last_full_charge_capacity: u32,
66 pub battery_technology: BatteryTechnology,
68 pub design_voltage: u32,
70 pub design_cap_of_warning: u32,
72 pub design_cap_of_low: u32,
74 pub cycle_count: u32,
76 pub measurement_accuracy: u32,
78 pub max_sampling_time: u32,
80 pub min_sampling_time: u32,
82 pub max_averaging_interval: u32,
84 pub min_averaging_interval: u32,
86 pub battery_capacity_granularity_1: u32,
88 pub battery_capacity_granularity_2: u32,
90 pub model_number: &'a [u8],
92 pub serial_number: &'a [u8],
94 pub battery_type: &'a [u8],
96 pub oem_info: &'a [u8],
98 pub battery_swapping_capability: BatterySwapCapability,
100}
101
102#[derive(Clone, Copy, PartialEq, Eq)]
103#[cfg_attr(feature = "defmt", derive(defmt::Format))]
104pub enum BixReturnSerializeErr {
106 StringSizeMismatch,
108 InputSliceTooSmall,
110}
111
112impl<'a> BixReturn<'a> {
113 pub fn to_bytes(
117 self,
118 dst_slice: &mut [u8],
119 model_num_size: usize,
120 serial_num_size: usize,
121 battery_type_size: usize,
122 oem_info_size: usize,
123 ) -> Result<(), BixReturnSerializeErr> {
124 const MODEL_NUM_START_IDX: usize = 64;
125 let model_num_end_idx: usize = MODEL_NUM_START_IDX + model_num_size;
126 let serial_num_start_idx = model_num_end_idx;
127 let serial_num_end_idx = serial_num_start_idx + serial_num_size;
128 let battery_type_start_idx = serial_num_end_idx;
129 let battery_type_end_idx = battery_type_start_idx + battery_type_size;
130 let oem_info_start_idx = battery_type_end_idx;
131 let oem_info_end_idx = oem_info_start_idx + oem_info_size;
132
133 if dst_slice.len() < oem_info_end_idx {
134 return Err(BixReturnSerializeErr::InputSliceTooSmall);
135 }
136
137 if self.model_number.len() != model_num_size
138 || self.serial_number.len() != serial_num_size
139 || self.battery_type.len() != battery_type_size
140 || self.oem_info.len() != oem_info_size
141 {
142 return Err(BixReturnSerializeErr::StringSizeMismatch);
143 }
144
145 dst_slice[..4].copy_from_slice(&u32::to_le_bytes(self.revision));
146 dst_slice[4..8].copy_from_slice(&u32::to_le_bytes(self.power_unit.into()));
147 dst_slice[8..12].copy_from_slice(&u32::to_le_bytes(self.design_capacity));
148 dst_slice[12..16].copy_from_slice(&u32::to_le_bytes(self.last_full_charge_capacity));
149 dst_slice[16..20].copy_from_slice(&u32::to_le_bytes(self.battery_technology.into()));
150 dst_slice[20..24].copy_from_slice(&u32::to_le_bytes(self.design_voltage));
151 dst_slice[24..28].copy_from_slice(&u32::to_le_bytes(self.design_cap_of_warning));
152 dst_slice[28..32].copy_from_slice(&u32::to_le_bytes(self.design_cap_of_low));
153 dst_slice[32..36].copy_from_slice(&u32::to_le_bytes(self.cycle_count));
154 dst_slice[36..40].copy_from_slice(&u32::to_le_bytes(self.measurement_accuracy));
155 dst_slice[40..44].copy_from_slice(&u32::to_le_bytes(self.max_sampling_time));
156 dst_slice[44..48].copy_from_slice(&u32::to_le_bytes(self.min_sampling_time));
157 dst_slice[48..52].copy_from_slice(&u32::to_le_bytes(self.max_averaging_interval));
158 dst_slice[52..56].copy_from_slice(&u32::to_le_bytes(self.min_averaging_interval));
159 dst_slice[56..60].copy_from_slice(&u32::to_le_bytes(self.battery_capacity_granularity_1));
160 dst_slice[60..64].copy_from_slice(&u32::to_le_bytes(self.battery_capacity_granularity_2));
161 dst_slice[MODEL_NUM_START_IDX..model_num_end_idx].copy_from_slice(self.model_number);
162 dst_slice[serial_num_start_idx..serial_num_end_idx].copy_from_slice(self.serial_number);
163 dst_slice[battery_type_start_idx..battery_type_end_idx].copy_from_slice(self.battery_type);
164 dst_slice[oem_info_start_idx..oem_info_end_idx].copy_from_slice(self.oem_info);
165 dst_slice[oem_info_end_idx..oem_info_end_idx + 4]
166 .copy_from_slice(&u32::to_le_bytes(self.battery_swapping_capability.into()));
167 Ok(())
168 }
169}
170
171#[repr(u32)]
173#[derive(Default, Copy, Clone, PartialEq, Eq, Immutable, IntoBytes)]
174#[cfg_attr(feature = "defmt", derive(defmt::Format))]
175pub enum PowerUnit {
176 MilliWatts = 0,
178 #[default]
180 MilliAmps = 1,
181}
182
183impl From<PowerUnit> for u32 {
184 fn from(value: PowerUnit) -> Self {
185 match value {
186 PowerUnit::MilliWatts => 0,
187 PowerUnit::MilliAmps => 1,
188 }
189 }
190}
191
192impl TryFrom<u32> for PowerUnit {
193 type Error = ();
194 fn try_from(value: u32) -> Result<Self, Self::Error> {
195 match value {
196 0 => Ok(Self::MilliWatts),
197 1 => Ok(Self::MilliAmps),
198 _ => Err(()),
199 }
200 }
201}
202
203#[repr(u32)]
205#[derive(Default, Copy, Clone, PartialEq, Eq, IntoBytes, Immutable)]
206#[cfg_attr(feature = "defmt", derive(defmt::Format))]
207pub enum BatteryTechnology {
208 Primary = 0,
210 #[default]
212 Secondary = 1,
213}
214
215impl From<BatteryTechnology> for u32 {
216 fn from(value: BatteryTechnology) -> Self {
217 match value {
218 BatteryTechnology::Primary => 0,
219 BatteryTechnology::Secondary => 1,
220 }
221 }
222}
223
224impl TryFrom<u32> for BatteryTechnology {
225 type Error = ();
226 fn try_from(value: u32) -> Result<Self, Self::Error> {
227 match value {
228 0 => Ok(Self::Primary),
229 1 => Ok(Self::Secondary),
230 _ => Err(()),
231 }
232 }
233}
234
235#[derive(Default, Copy, Clone, PartialEq, Eq, IntoBytes, Immutable)]
237#[repr(u32)]
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239pub enum BatterySwapCapability {
240 #[default]
242 NonSwappable = 0,
243 ColdSwappable = 1,
245 HotSwappable = 2,
247}
248
249impl From<BatterySwapCapability> for u32 {
250 fn from(value: BatterySwapCapability) -> Self {
251 match value {
252 BatterySwapCapability::NonSwappable => 0,
253 BatterySwapCapability::ColdSwappable => 1,
254 BatterySwapCapability::HotSwappable => 2,
255 }
256 }
257}
258
259impl TryFrom<u32> for BatterySwapCapability {
260 type Error = ();
261 fn try_from(value: u32) -> Result<Self, Self::Error> {
262 match value {
263 0 => Ok(Self::NonSwappable),
264 1 => Ok(Self::ColdSwappable),
265 2 => Ok(Self::HotSwappable),
266 _ => Err(()),
267 }
268 }
269}
270
271#[derive(Default, Copy, Clone, PartialEq, Eq, Immutable, IntoBytes)]
276#[cfg_attr(feature = "defmt", derive(defmt::Format))]
277pub struct PsrReturn {
278 pub power_source: PowerSource,
280}
281
282pub const PSR_RETURN_SIZE_BYTES: usize = 4;
284
285#[repr(u32)]
289#[derive(Default, Copy, Clone, PartialEq, Eq, Immutable, IntoBytes)]
290#[cfg_attr(feature = "defmt", derive(defmt::Format))]
291pub enum PowerSource {
292 #[default]
294 Offline = 0,
295
296 Online = 1,
298}
299
300impl From<PowerSource> for u32 {
301 fn from(value: PowerSource) -> Self {
302 match value {
303 PowerSource::Offline => 0,
304 PowerSource::Online => 1,
305 }
306 }
307}
308
309impl TryFrom<u32> for PowerSource {
310 type Error = ();
311 fn try_from(value: u32) -> Result<Self, Self::Error> {
312 match value {
313 0 => Ok(Self::Offline),
314 1 => Ok(Self::Online),
315 _ => Err(()),
316 }
317 }
318}
319
320#[repr(C)]
325#[derive(Default, PartialEq, Eq, FromBytes, Immutable)]
326#[cfg_attr(feature = "defmt", derive(defmt::Format))]
327pub struct Pif<'a> {
328 pub power_source_state: PowerSourceState,
330 pub max_output_power: u32,
334 pub max_input_power: u32,
338 pub model_number: &'a [u8],
340 pub serial_number: &'a [u8],
342 pub oem_info: &'a [u8],
344}
345
346#[derive(Clone, Copy, PartialEq, Eq)]
347#[cfg_attr(feature = "defmt", derive(defmt::Format))]
348pub enum PifSerializeErr {
350 StringSizeMismatch,
352 InputSliceTooSmall,
354}
355
356impl<'a> Pif<'a> {
357 pub fn to_bytes(
361 self,
362 dst_slice: &mut [u8],
363 model_num_size: usize,
364 serial_num_size: usize,
365 oem_info_size: usize,
366 ) -> Result<(), PifSerializeErr> {
367 const MODEL_NUM_START_IDX: usize = 12;
368 let model_num_end_idx: usize = MODEL_NUM_START_IDX + model_num_size;
369 let serial_num_start_idx = model_num_end_idx;
370 let serial_num_end_idx = serial_num_start_idx + serial_num_size;
371 let oem_info_start_idx = serial_num_end_idx;
372 let oem_info_end_idx = oem_info_start_idx + oem_info_size;
373
374 if dst_slice.len() < oem_info_end_idx {
375 return Err(PifSerializeErr::InputSliceTooSmall);
376 }
377
378 if self.model_number.len() != model_num_size
379 || self.serial_number.len() != serial_num_size
380 || self.oem_info.len() != oem_info_size
381 {
382 return Err(PifSerializeErr::StringSizeMismatch);
383 }
384
385 dst_slice[..4].copy_from_slice(&u32::to_le_bytes(self.power_source_state.bits()));
386 dst_slice[4..8].copy_from_slice(&u32::to_le_bytes(self.max_output_power));
387 dst_slice[8..12].copy_from_slice(&u32::to_le_bytes(self.max_input_power));
388 dst_slice[MODEL_NUM_START_IDX..model_num_end_idx].copy_from_slice(self.model_number);
389 dst_slice[serial_num_start_idx..serial_num_end_idx].copy_from_slice(self.serial_number);
390 dst_slice[oem_info_start_idx..oem_info_end_idx].copy_from_slice(self.oem_info);
391 Ok(())
392 }
393}
394
395#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
397#[cfg_attr(feature = "defmt", derive(defmt::Format))]
398pub struct PowerSourceState(u32);
399bitflags! {
400 impl PowerSourceState: u32 {
401 const REDUNDANT = 1 << 0;
403
404 const SHARED = 1 << 1;
406 }
407}
408
409#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
411#[cfg_attr(feature = "defmt", derive(defmt::Format))]
412pub struct Bps {
413 pub revision: u32,
417
418 pub instantaneous_peak_power_level: u32,
425
426 pub instantaneous_peak_power_period: u32,
431
432 pub sustainable_peak_power_level: u32,
439
440 pub sustainable_peak_power_period: u32,
445}
446
447pub const BPS_RETURN_SIZE_BYTES: usize = 20;
449
450#[derive(Default, Copy, Clone, PartialEq, Eq)]
452#[cfg_attr(feature = "defmt", derive(defmt::Format))]
453pub struct Btp {
454 pub trip_point: u32,
457}
458
459#[derive(Default, Copy, Clone, PartialEq, Eq)]
465#[cfg_attr(feature = "defmt", derive(defmt::Format))]
466pub struct Bpt {
467 pub revision: u32,
471
472 pub threshold_id: ThresholdId,
474
475 pub threshold_value: u32,
481}
482
483#[repr(u32)]
485#[derive(Default, Copy, Clone, PartialEq, Eq)]
486#[cfg_attr(feature = "defmt", derive(defmt::Format))]
487pub enum ThresholdId {
488 #[default]
489 ClearAll = 0,
491
492 InstantaneousPeakPower = 1,
494
495 SustainablePeakPower = 2,
497}
498
499impl TryFrom<u32> for ThresholdId {
500 type Error = ();
501 fn try_from(value: u32) -> Result<Self, Self::Error> {
502 match value {
503 0 => Ok(Self::ClearAll),
504 1 => Ok(Self::InstantaneousPeakPower),
505 2 => Ok(Self::SustainablePeakPower),
506 _ => Err(()),
507 }
508 }
509}
510
511#[repr(u32)]
513#[derive(Copy, Clone, PartialEq, Eq)]
514#[cfg_attr(feature = "defmt", derive(defmt::Format))]
515pub enum BptReturnStatus {
516 Success = 0x00000000,
518
519 InvalidThresholdValue = 0x00000001,
521
522 HardwareTimeout = 0x00000002,
524
525 UnknownHardwareError = 0x00000003,
527
528 UnsupportedThresholdType = 0x00000004,
530
531 UnsupportedRevision = 0x00000005,
533}
534
535#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
540#[cfg_attr(feature = "defmt", derive(defmt::Format))]
541pub struct Bpc {
542 pub revision: u32,
546
547 pub power_threshold_support: PowerThresholdSupport,
551
552 pub max_instantaneous_peak_power_threshold: u32,
557
558 pub max_sustainable_peak_power_threshold: u32,
563}
564
565pub const BPC_RETURN_SIZE_BYTES: usize = 16;
567
568#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
572#[cfg_attr(feature = "defmt", derive(defmt::Format))]
573pub struct PowerThresholdSupport(u32);
574bitflags! {
575 impl PowerThresholdSupport: u32 {
576 const INSTANTANEOUS = 1 << 0;
578 const SUSTAINABLE = 1 << 1;
580 }
581}
582
583#[derive(Default, Copy, Clone, PartialEq, Eq)]
585#[cfg_attr(feature = "defmt", derive(defmt::Format))]
586pub struct Bmc {
587 pub maintenance_control_flags: BmcControlFlags,
589}
590
591#[derive(Default, Copy, Clone, PartialEq, Eq)]
595#[cfg_attr(feature = "defmt", derive(defmt::Format))]
596pub struct BmcControlFlags(u32);
597bitflags! {
598 impl BmcControlFlags: u32 {
599 const CALIBRATION_CYCLE = 1 << 0;
601
602 const DISABLE_CHARGING = 1 << 1;
604
605 const ALLOW_DISCHARGE_ON_AC = 1 << 2;
607
608 const SUSPEND_CHARGE_LIMITING = 1 << 3;
610 }
611}
612
613#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
618#[cfg_attr(feature = "defmt", derive(defmt::Format))]
619pub struct Bmd {
620 pub status_flags: BmdStatusFlags,
622
623 pub capability_flags: BmdCapabilityFlags,
625
626 pub recalibrate_count: u32,
631
632 pub quick_recalibrate_time: u32,
638
639 pub slow_recalibrate_time: u32,
645}
646
647pub const BMD_RETURN_SIZE_BYTES: usize = 20;
649
650#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
654#[cfg_attr(feature = "defmt", derive(defmt::Format))]
655pub struct BmdStatusFlags(u32);
656bitflags! {
657 impl BmdStatusFlags: u32 {
658 const AML_CALIBRATION_ACTIVE = 1 << 0;
660
661 const CHARGING_DISABLED = 1 << 1;
663
664 const DISCHARGE_ON_AC = 1 << 2;
666
667 const RECALIBRATION_NEEDED = 1 << 3;
669
670 const STANDBY_RECOMMENDED = 1 << 4;
672
673 const CHARGE_LIMIT_THERMAL_LOCK = 1 << 5;
675
676 const CHARGE_LIMIT_PROTECTION_LOCK = 1 << 6;
678 }
679}
680
681#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
685#[cfg_attr(feature = "defmt", derive(defmt::Format))]
686pub struct BmdCapabilityFlags(u32);
687bitflags! {
688 impl BmdCapabilityFlags: u32 {
689 const AML_CALIBRATION_SUPPORTED = 1 << 0;
691
692 const CHARGER_DISABLE_SUPPORTED = 1 << 1;
694
695 const DISCHARGE_ON_AC_SUPPORTED = 1 << 2;
697
698 const GLOBAL_CONTROL = 1 << 3;
700
701 const FULL_CHARGE_BEFORE_CALIBRATION = 1 << 4;
703
704 const CHARGE_LIMIT_SUSPEND_SUPPORTED = 1 << 5;
706 }
707}
708
709#[derive(Default, Copy, Clone, PartialEq, Eq)]
714#[cfg_attr(feature = "defmt", derive(defmt::Format))]
715pub struct Bct {
716 pub charge_level_percent: u32,
720}
721
722#[repr(u32)]
726#[derive(Default, Copy, Clone, PartialEq, Eq)]
727#[cfg_attr(feature = "defmt", derive(defmt::Format))]
728pub enum BctReturnResult {
729 InvalidTarget = 0x00000000,
731
732 EstimatedTime(u32),
734
735 #[default]
737 Unknown = 0xFFFFFFFF,
738}
739
740pub const BCT_RETURN_SIZE_BYTES: usize = 4;
742
743impl From<u32> for BctReturnResult {
744 fn from(value: u32) -> Self {
745 match value {
746 0x00000000 => BctReturnResult::InvalidTarget,
747 0xFFFFFFFF => BctReturnResult::Unknown,
748 seconds => BctReturnResult::EstimatedTime(seconds),
749 }
750 }
751}
752
753impl From<BctReturnResult> for u32 {
754 fn from(value: BctReturnResult) -> Self {
755 match value {
756 BctReturnResult::InvalidTarget => 0x00000000,
757 BctReturnResult::Unknown => 0xFFFFFFFF,
758 BctReturnResult::EstimatedTime(seconds) => seconds,
759 }
760 }
761}
762
763impl From<BctReturnResult> for [u8; BCT_RETURN_SIZE_BYTES] {
764 fn from(value: BctReturnResult) -> Self {
765 u32::to_le_bytes(u32::from(value))
766 }
767}
768
769#[derive(Default, Copy, Clone, PartialEq, Eq)]
774#[cfg_attr(feature = "defmt", derive(defmt::Format))]
775pub struct Btm {
776 pub discharge_rate: u32,
781}
782
783#[repr(u32)]
787#[derive(Default, Copy, Clone, PartialEq, Eq)]
788#[cfg_attr(feature = "defmt", derive(defmt::Format))]
789pub enum BtmReturnResult {
790 RateTooHighOrBatteryCritical = 0x00000000,
792
793 EstimatedRuntime(u32),
795
796 #[default]
798 Unknown = 0xFFFFFFFF,
799}
800
801pub const BTM_RETURN_SIZE_BYTES: usize = 4;
803
804impl From<u32> for BtmReturnResult {
805 fn from(value: u32) -> Self {
806 match value {
807 0x00000000 => BtmReturnResult::RateTooHighOrBatteryCritical,
808 0xFFFFFFFF => BtmReturnResult::Unknown,
809 seconds => BtmReturnResult::EstimatedRuntime(seconds),
810 }
811 }
812}
813
814impl From<BtmReturnResult> for u32 {
815 fn from(value: BtmReturnResult) -> Self {
816 match value {
817 BtmReturnResult::RateTooHighOrBatteryCritical => 0x00000000,
818 BtmReturnResult::Unknown => 0xFFFFFFFF,
819 BtmReturnResult::EstimatedRuntime(seconds) => seconds,
820 }
821 }
822}
823
824impl From<BtmReturnResult> for [u8; BTM_RETURN_SIZE_BYTES] {
825 fn from(value: BtmReturnResult) -> Self {
826 u32::to_le_bytes(u32::from(value))
827 }
828}
829
830#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
835#[cfg_attr(feature = "defmt", derive(defmt::Format))]
836pub struct Bms {
837 pub sampling_time_ms: u32,
841}
842
843#[repr(u32)]
847#[derive(Copy, Clone, PartialEq, Eq)]
848#[cfg_attr(feature = "defmt", derive(defmt::Format))]
849pub enum BmsReturnResult {
850 Success = 0,
852
853 OutOfRange = 1,
855}
856
857impl From<BmsReturnResult> for u32 {
858 fn from(value: BmsReturnResult) -> Self {
859 match value {
860 BmsReturnResult::Success => 0,
861 BmsReturnResult::OutOfRange => 1,
862 }
863 }
864}
865
866#[derive(Default, Copy, Clone, PartialEq, Eq)]
871#[cfg_attr(feature = "defmt", derive(defmt::Format))]
872pub struct Bma {
873 pub averaging_interval_ms: u32,
877}
878
879#[repr(u32)]
883#[derive(Copy, Clone, PartialEq, Eq)]
884#[cfg_attr(feature = "defmt", derive(defmt::Format))]
885pub enum BmaReturnResult {
886 Success = 0,
888
889 OutOfRange = 1,
891}
892
893impl From<BmaReturnResult> for u32 {
894 fn from(value: BmaReturnResult) -> Self {
895 match value {
896 BmaReturnResult::Success => 0,
897 BmaReturnResult::OutOfRange => 1,
898 }
899 }
900}
901
902#[derive(Default, Copy, Clone, PartialEq, Eq, FromBytes, IntoBytes, Immutable)]
906#[cfg_attr(feature = "defmt", derive(defmt::Format))]
907pub struct StaReturn(u32);
908bitflags! {
909 impl StaReturn: u32 {
910 const DEVICE_PRESENT = 1 << 0;
912
913 const DEVICE_ENABLED = 1 << 1;
915
916 const DEVICE_SHOULD_SHOWN_UI = 1 << 2;
918
919 const DEVICE_FUNCTIONING = 1 << 3;
921
922 const BATTERY_PRESENT = 1 << 4;
924 }
925}
926
927pub const STA_RETURN_SIZE_BYTES: usize = 4;