1pub mod error;
4pub mod parameter;
5pub mod request;
6pub mod response;
7
8use error::RdmError;
9pub use macaddr;
10
11pub const RDM_START_CODE_BYTE: u8 = 0xcc;
12pub const RDM_SUB_START_CODE_BYTE: u8 = 0x01;
13
14pub const DISCOVERY_UNIQUE_BRANCH_PREAMBLE_BYTE: u8 = 0xfe;
15pub const DISCOVERY_UNIQUE_BRANCH_PREAMBLE_SEPARATOR_BYTE: u8 = 0xaa;
16
17pub const MAX_RDM_FRAME_LENGTH: usize = 257;
18pub const MAX_RDM_PARAMETER_DATA_LENGTH: usize = 231;
19
20#[cfg(not(feature = "alloc"))]
21use heapless::Vec;
22
23#[cfg(feature = "alloc")]
24pub type EncodedFrame = Vec<u8>;
25#[cfg(not(feature = "alloc"))]
26pub type EncodedFrame = Vec<u8, MAX_RDM_FRAME_LENGTH>;
27
28#[cfg(feature = "alloc")]
29pub type EncodedParameterData = Vec<u8>;
30#[cfg(not(feature = "alloc"))]
31pub type EncodedParameterData = Vec<u8, MAX_RDM_PARAMETER_DATA_LENGTH>;
32
33#[derive(Copy, Clone, Debug, PartialEq)]
34pub enum CommandClass {
35 DiscoveryCommand = 0x10,
36 DiscoveryCommandResponse = 0x11,
37 GetCommand = 0x20,
38 GetCommandResponse = 0x21,
39 SetCommand = 0x30,
40 SetCommandResponse = 0x31,
41}
42
43impl TryFrom<u8> for CommandClass {
44 type Error = RdmError;
45
46 fn try_from(value: u8) -> Result<Self, Self::Error> {
47 match value {
48 0x10 => Ok(Self::DiscoveryCommand),
49 0x11 => Ok(Self::DiscoveryCommandResponse),
50 0x20 => Ok(Self::GetCommand),
51 0x21 => Ok(Self::GetCommandResponse),
52 0x30 => Ok(Self::SetCommand),
53 0x31 => Ok(Self::SetCommandResponse),
54 _ => Err(RdmError::InvalidCommandClass(value)),
55 }
56 }
57}
58
59#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
60pub struct DeviceUID {
61 pub manufacturer_id: u16,
62 pub device_id: u32,
63}
64
65impl DeviceUID {
66 pub const ALL_MANUFACTURERS_ID: u16 = 0xffff;
67 pub const ALL_DEVICES_ID: u32 = 0xffffffff;
68
69 pub const fn new(manufacturer_id: u16, device_id: u32) -> Self {
70 Self {
71 manufacturer_id,
72 device_id,
73 }
74 }
75
76 pub const fn new_dynamic(mut manufacturer_id: u16, device_id: u32) -> Self {
77 manufacturer_id |= 0x8000;
78
79 Self {
80 manufacturer_id,
81 device_id,
82 }
83 }
84
85 pub const fn broadcast_to_devices_with_manufacturer_id(manufacturer_id: u16) -> Self {
86 Self {
87 manufacturer_id,
88 device_id: Self::ALL_DEVICES_ID,
89 }
90 }
91
92 pub const fn broadcast_to_devices_with_manufacturer_id_dynamic(
93 mut manufacturer_id: u16,
94 device_id: u32,
95 ) -> Self {
96 manufacturer_id |= 0x8000;
97
98 Self {
99 manufacturer_id,
100 device_id,
101 }
102 }
103
104 pub const fn broadcast_to_all_devices() -> Self {
105 Self {
106 manufacturer_id: Self::ALL_MANUFACTURERS_ID,
107 device_id: Self::ALL_DEVICES_ID,
108 }
109 }
110
111 pub fn is_dynamic(&self) -> bool {
112 self.manufacturer_id & 0x8000 != 0
113 }
114}
115
116impl From<[u8; 6]> for DeviceUID {
117 fn from(bytes: [u8; 6]) -> Self {
118 let manufacturer_id = u16::from_be_bytes([bytes[0], bytes[1]]);
119 let device_id = u32::from_be_bytes([bytes[2], bytes[3], bytes[4], bytes[5]]);
120
121 DeviceUID {
122 manufacturer_id,
123 device_id,
124 }
125 }
126}
127
128impl From<DeviceUID> for [u8; 6] {
129 fn from(uid: DeviceUID) -> Self {
130 let manufacturer_id_bytes = uid.manufacturer_id.to_be_bytes();
131 let device_id_bytes = uid.device_id.to_be_bytes();
132
133 [
134 manufacturer_id_bytes[0],
135 manufacturer_id_bytes[1],
136 device_id_bytes[0],
137 device_id_bytes[1],
138 device_id_bytes[2],
139 device_id_bytes[3],
140 ]
141 }
142}
143
144pub fn bsd_16_crc(packet: &[u8]) -> u16 {
145 packet
146 .iter()
147 .fold(0_u16, |sum, byte| (sum.overflowing_add(*byte as u16).0))
148}
149
150#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
151pub enum SubDeviceId {
152 RootDevice,
153 Id(u16),
154 AllDevices,
155}
156
157impl From<u16> for SubDeviceId {
158 fn from(value: u16) -> SubDeviceId {
159 match value {
160 0x0000 => SubDeviceId::RootDevice,
161 0xffff => SubDeviceId::AllDevices,
162 _ => SubDeviceId::Id(value),
163 }
164 }
165}
166
167impl From<SubDeviceId> for u16 {
168 fn from(sub_device: SubDeviceId) -> u16 {
169 match sub_device {
170 SubDeviceId::RootDevice => 0x0000,
171 SubDeviceId::AllDevices => 0xffff,
172 SubDeviceId::Id(id) => id,
173 }
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn should_create_static_device_uid() {
183 let device_uid = DeviceUID::new(0x1234, 0x56789abc);
184
185 assert_eq!(
186 device_uid,
187 DeviceUID {
188 manufacturer_id: 0x1234,
189 device_id: 0x56789abc
190 }
191 );
192 assert!(!device_uid.is_dynamic());
193 }
194
195 #[test]
196 fn should_create_dynamic_device_uid() {
197 let device_uid = DeviceUID::new_dynamic(0x1234, 0x56789abc);
198
199 assert_eq!(
200 device_uid,
201 DeviceUID {
202 manufacturer_id: 0x9234,
203 device_id: 0x56789abc
204 }
205 );
206 assert!(device_uid.is_dynamic());
207 }
208
209 #[test]
210 fn should_array_to_convert_device_uid() {
211 assert_eq!(
212 DeviceUID::from([0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]),
213 DeviceUID::new(0x1234, 0x56789abc)
214 );
215 }
216
217 #[test]
218 fn should_convert_device_uid_to_array() {
219 assert_eq!(
220 <[u8; 6]>::from(DeviceUID::new(0x1234, 0x56789abc)),
221 [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc]
222 );
223 }
224}