1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use bitflags::bitflags;
#[allow(unused_imports, reason = "It is only unused in some feature sets")]
use crate::FieldIter;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use {super::SerializeUbxPacketFields, crate::serde::ser::SerializeMap};
use crate::{
cfg_val::{CfgKey, CfgVal},
error::ParserError,
ubx_checksum, UbxPacketMeta,
};
use ublox_derive::{ubx_extend, ubx_extend_bitflags, ubx_packet_recv, ubx_packet_send};
#[ubx_packet_send]
#[ubx(
class = 0x06,
id = 0x8a,
max_payload_len = 772, // 4 + (4 + 8) * 64
)]
struct CfgValSet<'a> {
/// Message version
version: u8,
/// The layers from which the configuration items should be retrieved
#[ubx(map_type = CfgLayerSet)]
layers: u8,
reserved1: u16,
cfg_data: &'a [CfgVal],
}
/// The CfgValGet message is limited to requesting a maximum of 64 key-value pairs.
pub const MAX_CFG_KEYS: u16 = 64;
#[ubx_packet_send]
#[ubx(
class = 0x06,
id = 0x8b,
max_payload_len = 260, // 4 + sizeof(u32) * MAX_CFG_KEYS
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// This message is limited to containing a maximum of 64 key IDs.
/// This message returns a UBX-ACK-NAK
/// - if any key is unknown to the receiver FW
/// - if the layer field specifies an invalid layer to get the value from
/// - if the keys array specifies more than 64 key IDs.
struct CfgValGetRequest<'a> {
/// Message version
version: u8,
/// The layers from which the configuration items should be retrieved
#[ubx(map_type = CfgLayerGet)]
layers: u8,
position: u16,
cfg_keys: &'a [CfgKey],
}
#[ubx_packet_recv]
#[ubx(
class = 0x06,
id = 0x8b,
max_payload_len = 772, // 4 + (sizeof(u32) + sizeof(largest val)) * MAX_CFG_KEYS
)]
struct CfgValGetResponse {
/// Message version
version: u8,
#[ubx(map_type = CfgLayerGet)]
layers: u8,
position: u16,
#[ubx(
map_type = CfgValIter,
from = CfgValIter::new,
may_fail,
is_valid = CfgValIter::is_valid,
)]
cfg_data: [u8; 0],
}
/// The [CfgLayerGet] enum is used to specify the configuration layer to read from.
/// The configuration system in the ublox device is stacked, so a property
/// may be empty for a particular layer and you will receive a NAK.
#[ubx_extend]
#[ubx(from, into_raw, rest_reserved)]
#[repr(u8)]
#[derive(Debug, Copy, Clone)]
pub enum CfgLayerGet {
/// Read from RAM
Ram = 0,
/// Read from BBR (battery backed RAM)
Bbr = 1,
/// Read from Flash, if available
Flash = 2,
/// Read the current configuration from the active source
Default = 7,
}
#[derive(Debug, Clone)]
pub struct CfgValIter<'a> {
data: &'a [u8],
}
impl<'a> CfgValIter<'a> {
fn new(data: &'a [u8]) -> Self {
Self { data }
}
fn is_valid(bytes: &[u8]) -> bool {
// we need at least 5 bytes for a key id (4) + val (1)
bytes.len() >= 5
}
}
impl core::iter::Iterator for CfgValIter<'_> {
type Item = CfgVal;
fn next(&mut self) -> Option<Self::Item> {
if Self::is_valid(self.data) {
if let Some(cfg_val) = CfgVal::parse(self.data) {
self.data = &self.data[cfg_val.len()..];
return Some(cfg_val);
}
// TODO: Is there some logging mechanism?
// eprintln!("Failure parsing key in (key,value) list, {:?}", self.data);
}
None
}
}
/// The `CfgLayerSet` defines the configuration layer used to set configuration values to.
/// The definition of the Layers for updating the configuration values is different than
/// the definition of the Layers for reading values, see [CfgLayerGet]
#[ubx_extend_bitflags]
#[ubx(from, into_raw, rest_reserved)]
bitflags! {
/// A mask describing where configuration is applied.
pub struct CfgLayerSet: u8 {
const RAM = 0b001;
const BBR = 0b010;
const FLASH = 0b100;
}
}
impl Default for CfgLayerSet {
fn default() -> Self {
Self::RAM | Self::BBR | Self::FLASH
}
}