1use crate::{
4 decode::{Decode, DecodeError, DecodeErrorKind},
5 encode::{Encode, MessageEncoder},
6 varint::VarU16,
7 version::Version,
8};
9
10use super::{COMMAND_HEADER, REPLY_HEADER};
11
12pub mod cmds {
17 pub const ACK: u8 = 0x33;
18 pub const QUERY_1: u8 = 0x21;
19 pub const USER_CDC: u8 = 0x56;
20 pub const CON_CDC: u8 = 0x58;
21 pub const SYSTEM_VERSION: u8 = 0xA4;
22 pub const EEPROM_ERASE: u8 = 0x31;
23 pub const USER_ENTER: u8 = 0x60;
24 pub const USER_CATALOG: u8 = 0x61;
25 pub const FLASH_ERASE: u8 = 0x63;
26 pub const FLASH_WRITE: u8 = 0x64;
27 pub const FLASH_READ: u8 = 0x65;
28 pub const USER_EXIT: u8 = 0x66;
29 pub const USER_PLAY: u8 = 0x67;
30 pub const USER_STOP: u8 = 0x68;
31 pub const COMPONENT_GET: u8 = 0x69;
32 pub const USER_SLOT_GET: u8 = 0x78;
33 pub const USER_SLOT_SET: u8 = 0x79;
34 pub const BRAIN_NAME_GET: u8 = 0x44;
35}
36
37use bitflags::bitflags;
38use cmds::{QUERY_1, SYSTEM_VERSION};
39
40#[derive(Clone, Copy, Eq, PartialEq)]
57pub struct CdcCommandPacket<const CMD: u8, P: Encode> {
58 payload: P,
59}
60
61impl<const CMD: u8, P: Encode> CdcCommandPacket<CMD, P> {
62 pub const HEADER: [u8; 4] = COMMAND_HEADER;
64
65 pub fn new(payload: P) -> Self {
67 Self { payload }
68 }
69}
70
71impl<const CMD: u8, P: Encode> Encode for CdcCommandPacket<CMD, P> {
72 fn size(&self) -> usize {
73 let payload_size = self.payload.size();
74
75 5 + if payload_size == 0 {
76 0
77 } else if payload_size > (u8::MAX >> 1) as _ {
78 2
79 } else {
80 1
81 } + payload_size
82 }
83
84 fn encode(&self, data: &mut [u8]) {
85 Self::HEADER.encode(data);
86 data[4] = CMD;
87
88 let payload_size = self.payload.size();
89
90 if payload_size > 0 {
92 let mut enc = MessageEncoder::new_with_position(data, 5);
93
94 enc.write(&VarU16::new(payload_size as u16));
95 enc.write(&self.payload);
96 }
97 }
98}
99
100#[derive(Clone, Copy, Eq, PartialEq)]
117pub struct CdcReplyPacket<const CMD: u8, P: Decode> {
118 pub size: u16,
120
121 pub payload: P,
125}
126
127impl<const CMD: u8, P: Decode> CdcReplyPacket<CMD, P> {
128 pub const HEADER: [u8; 2] = REPLY_HEADER;
130}
131
132impl<const CMD: u8, P: Decode> Decode for CdcReplyPacket<CMD, P> {
133 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
134 if <[u8; 2]>::decode(data)? != Self::HEADER {
135 return Err(DecodeError::new::<Self>(DecodeErrorKind::InvalidHeader));
136 }
137
138 let cmd = u8::decode(data)?;
139 if cmd != CMD {
140 return Err(DecodeError::new::<Self>(DecodeErrorKind::UnexpectedByte {
141 name: "cmd",
142 value: cmd,
143 expected: &[CMD],
144 }));
145 }
146
147 let payload_size = VarU16::decode(data)?.into_inner();
148 let payload = P::decode(data)?;
149
150 Ok(Self {
151 size: payload_size,
152 payload,
153 })
154 }
155}
156
157pub type SystemVersionPacket = CdcCommandPacket<SYSTEM_VERSION, ()>;
158pub type SystemVersionReplyPacket = CdcReplyPacket<SYSTEM_VERSION, SystemVersionReplyPayload>;
159
160#[derive(Debug, Clone, Copy, Eq, PartialEq)]
161pub struct SystemVersionReplyPayload {
162 pub version: Version,
163 pub product_type: ProductType,
164 pub flags: ProductFlags,
165}
166impl Decode for SystemVersionReplyPayload {
167 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
168 let version = Version::decode(data)?;
169 let product_type = ProductType::decode(data)?;
170 let flags = ProductFlags::from_bits_truncate(u8::decode(data)?);
171
172 Ok(Self {
173 version,
174 product_type,
175 flags,
176 })
177 }
178}
179
180pub type Query1Packet = CdcCommandPacket<QUERY_1, ()>;
181pub type Query1ReplyPacket = CdcReplyPacket<QUERY_1, Query1ReplyPayload>;
182
183#[derive(Debug, Clone, Copy, Eq, PartialEq)]
184pub struct Query1ReplyPayload {
185 pub version_1: u32,
186 pub version_2: u32,
187
188 pub boot_source: u8,
190
191 pub count: u8,
193}
194
195impl Decode for Query1ReplyPayload {
196 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
197 let version_1 = u32::decode(data)?;
198 let version_2 = u32::decode(data)?;
199 let boot_source = u8::decode(data)?;
200 let count = u8::decode(data)?;
201
202 Ok(Self {
203 version_1,
204 version_2,
205 boot_source,
206 count,
207 })
208 }
209}
210
211#[derive(Debug, Clone, Copy, Eq, PartialEq)]
212#[repr(u16)]
213pub enum ProductType {
214 Brain = 0x10,
215 Controller = 0x11,
216}
217impl Decode for ProductType {
218 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
219 let data = <[u8; 2]>::decode(data)?;
220
221 match data[1] {
222 0x10 => Ok(Self::Brain),
223 0x11 => Ok(Self::Controller),
224 v => Err(DecodeError::new::<Self>(DecodeErrorKind::UnexpectedByte {
225 name: "ProductType",
226 value: v,
227 expected: &[0x10, 0x11],
228 })),
229 }
230 }
231}
232
233bitflags! {
234 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
235 pub struct ProductFlags: u8 {
236 const CONNECTED_CABLE = 1 << 0; const CONNECTED_WIRELESS = 1 << 1;
241 }
242}