1#![allow(clippy::too_many_arguments)]
2use crate::*;
3
4pub fn encode_tlv(buffer: &mut PacketBuffer, tlv: &TLVBlock) -> Result<()> {
5 buffer.write_u16(tlv.type_id)?;
6 buffer.write_u16(tlv.length())?;
7 buffer.write_bytes(tlv.value)
8}
9
10pub fn encode_tid_level(buffer: &mut PacketBuffer, dmx_data: &[u8]) -> Result<()> {
11 if dmx_data.is_empty() || dmx_data.len() > MAX_DMX_SLOTS as usize {
12 return Err(SigNetError::InvalidArgument);
13 }
14 let tlv = TLVBlock {
15 type_id: TID_LEVEL,
16 value: dmx_data,
17 };
18 encode_tlv(buffer, &tlv)
19}
20
21pub fn encode_tid_priority(buffer: &mut PacketBuffer, priority_data: &[u8]) -> Result<()> {
22 if priority_data.is_empty() || priority_data.len() > MAX_DMX_SLOTS as usize {
23 return Err(SigNetError::InvalidArgument);
24 }
25 let tlv = TLVBlock {
26 type_id: TID_PRIORITY,
27 value: priority_data,
28 };
29 encode_tlv(buffer, &tlv)
30}
31
32pub fn encode_tid_sync(buffer: &mut PacketBuffer) -> Result<()> {
33 buffer.write_u16(TID_SYNC)?;
34 buffer.write_u16(0)
35}
36
37pub fn encode_tid_poll(
38 buffer: &mut PacketBuffer,
39 manager_tuid: &[u8; TUID_LENGTH],
40 soem_code: SoemCode,
41 tuid_lo: &[u8; TUID_LENGTH],
42 tuid_hi: &[u8; TUID_LENGTH],
43 target_endpoint: u16,
44 query_level: u8,
45) -> Result<()> {
46 buffer.write_u16(TID_POLL)?;
47 buffer.write_u16(TID_POLL_VALUE_LEN)?;
48 buffer.write_bytes(manager_tuid)?;
49 buffer.write_u32(soem_code)?;
50 buffer.write_bytes(tuid_lo)?;
51 buffer.write_bytes(tuid_hi)?;
52 buffer.write_u16(target_endpoint)?;
53 buffer.write_byte(query_level)
54}
55
56pub fn encode_tid_poll_reply(
57 buffer: &mut PacketBuffer,
58 tuid: &[u8; TUID_LENGTH],
59 soem_code: SoemCode,
60 change_count: u16,
61) -> Result<()> {
62 buffer.write_u16(TID_POLL_REPLY)?;
63 buffer.write_u16(TID_POLL_REPLY_VALUE_LEN)?;
64 buffer.write_bytes(tuid)?;
65 buffer.write_u32(soem_code)?;
66 buffer.write_u16(change_count)
67}
68
69pub fn encode_tid_rt_protocol_version(buffer: &mut PacketBuffer, protocol_version: u8) -> Result<()> {
70 buffer.write_u16(TID_RT_PROTOCOL_VERSION)?;
71 buffer.write_u16(1)?;
72 buffer.write_byte(protocol_version)
73}
74
75pub fn encode_tid_rt_firmware_version(
76 buffer: &mut PacketBuffer,
77 machine_version_id: u32,
78 version_string: &str,
79) -> Result<()> {
80 let vs = version_string.as_bytes();
81 buffer.write_u16(TID_RT_FIRMWARE_VERSION)?;
82 buffer.write_u16(4 + vs.len() as u16)?;
83 buffer.write_u32(machine_version_id)?;
84 buffer.write_bytes(vs)
85}
86
87pub fn encode_tid_rt_role_capability(buffer: &mut PacketBuffer, role_capability_bits: u8) -> Result<()> {
88 buffer.write_u16(TID_RT_ROLE_CAPABILITY)?;
89 buffer.write_u16(1)?;
90 buffer.write_byte(role_capability_bits)
91}
92
93pub fn encode_tid_preview(buffer: &mut PacketBuffer, dmx_data: &[u8]) -> Result<()> {
94 if dmx_data.is_empty() || dmx_data.len() > MAX_DMX_SLOTS as usize {
95 return Err(SigNetError::InvalidArgument);
96 }
97 let tlv = TLVBlock {
98 type_id: TID_PREVIEW,
99 value: dmx_data,
100 };
101 encode_tlv(buffer, &tlv)
102}
103
104pub fn encode_tid_timecode(
106 buffer: &mut PacketBuffer,
107 hours: u8,
108 minutes: u8,
109 seconds: u8,
110 frames: u8,
111 tc_type: u8,
112) -> Result<()> {
113 buffer.write_u16(TID_TIMECODE)?;
114 buffer.write_u16(5)?;
115 buffer.write_byte(hours)?;
116 buffer.write_byte(minutes)?;
117 buffer.write_byte(seconds)?;
118 buffer.write_byte(frames)?;
119 buffer.write_byte(tc_type)
120}
121
122pub fn encode_tid_universe(
124 buffer: &mut PacketBuffer,
125 universe: u16,
126 command: u8,
127 multicast_ip: &[u8; 4],
128) -> Result<()> {
129 buffer.write_u16(TID_UNIVERSE)?;
130 buffer.write_u16(7)?;
131 buffer.write_u16(universe)?;
132 buffer.write_byte(command)?;
133 buffer.write_bytes(multicast_ip)
134}
135
136pub fn encode_tid_rt_mult_override(buffer: &mut PacketBuffer, state: u8) -> Result<()> {
138 buffer.write_u16(TID_RT_MULT_OVERRIDE)?;
139 buffer.write_u16(1)?;
140 buffer.write_byte(state)
141}
142
143pub fn encode_tid_rt_otw_capability(
145 buffer: &mut PacketBuffer,
146 listener_port: u16,
147 protocols_bitfield: u8,
148) -> Result<()> {
149 buffer.write_u16(TID_RT_OTW_CAPABILITY)?;
150 buffer.write_u16(3)?;
151 buffer.write_u16(listener_port)?;
152 buffer.write_byte(protocols_bitfield)
153}
154
155pub fn encode_tid_rt_reboot(buffer: &mut PacketBuffer, reboot_type: u8) -> Result<()> {
157 buffer.write_u16(TID_RT_REBOOT)?;
158 buffer.write_u16(5)?;
159 buffer.write_byte(reboot_type)?;
160 buffer.write_bytes(b"BOOT")
161}
162
163pub fn build_startup_announce_payload(
165 buffer: &mut PacketBuffer,
166 tuid: &[u8; TUID_LENGTH],
167 soem_code: SoemCode,
168 firmware_version_id: u32,
169 firmware_version_string: &str,
170 protocol_version: u8,
171 role_capability_bits: u8,
172 endpoint_count: u16,
173 change_count: u16,
174 mult_override_state: u8,
175 otw_capability: Option<(u16, u8)>,
176) -> Result<()> {
177 encode_tid_poll_reply(buffer, tuid, soem_code, change_count)?;
179 encode_tid_rt_firmware_version(buffer, firmware_version_id, firmware_version_string)?;
181 encode_tid_rt_protocol_version(buffer, protocol_version)?;
183 encode_tid_rt_role_capability(buffer, role_capability_bits)?;
185 let ec = endpoint_count.to_be_bytes();
187 encode_tlv(buffer, &TLVBlock { type_id: TID_RT_ENDPOINT_COUNT, value: &ec })?;
188 encode_tid_rt_mult_override(buffer, mult_override_state)?;
190 if let Some((port, protocols)) = otw_capability {
192 encode_tid_rt_otw_capability(buffer, port, protocols)?;
193 }
194 Ok(())
195}