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 mut payload_data = data
149 .get(0..(payload_size as usize))
150 .ok_or_else(|| DecodeError::new::<Self>(DecodeErrorKind::UnexpectedEnd))?;
151 *data = &data[(payload_size as usize)..];
152
153 let payload = P::decode(&mut payload_data)?;
154
155 Ok(Self {
156 size: payload_size,
157 payload,
158 })
159 }
160}
161
162pub type SystemVersionPacket = CdcCommandPacket<SYSTEM_VERSION, ()>;
163pub type SystemVersionReplyPacket = CdcReplyPacket<SYSTEM_VERSION, SystemVersionReplyPayload>;
164
165#[derive(Debug, Clone, Copy, Eq, PartialEq)]
166pub struct SystemVersionReplyPayload {
167 pub version: Version,
168 pub product_type: ProductType,
169 pub flags: ProductFlags,
170}
171impl Decode for SystemVersionReplyPayload {
172 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
173 let version = Version::decode(data)?;
174 let product_type = ProductType::decode(data)?;
175 let flags = ProductFlags::from_bits_truncate(u8::decode(data)?);
176
177 Ok(Self {
178 version,
179 product_type,
180 flags,
181 })
182 }
183}
184
185pub type Query1Packet = CdcCommandPacket<QUERY_1, ()>;
186pub type Query1ReplyPacket = CdcReplyPacket<QUERY_1, Query1ReplyPayload>;
187
188#[derive(Debug, Clone, Copy, Eq, PartialEq)]
189pub struct Query1ReplyPayload {
190 pub version_1: u32,
191 pub version_2: u32,
192
193 pub boot_source: u8,
195
196 pub count: u8,
198}
199
200impl Decode for Query1ReplyPayload {
201 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
202 let version_1 = u32::decode(data)?;
203 let version_2 = u32::decode(data)?;
204 let boot_source = u8::decode(data)?;
205 let count = u8::decode(data)?;
206
207 Ok(Self {
208 version_1,
209 version_2,
210 boot_source,
211 count,
212 })
213 }
214}
215
216#[derive(Debug, Clone, Copy, Eq, PartialEq)]
217#[repr(u16)]
218pub enum ProductType {
219 V5Brain = 0x10,
220 ExpBrain = 0x60,
221 Controller = 0x11,
222}
223impl Decode for ProductType {
224 fn decode(data: &mut &[u8]) -> Result<Self, DecodeError> {
225 let data = <[u8; 2]>::decode(data)?;
226
227 match data[1] {
228 0x10 => Ok(Self::V5Brain),
229 0x60 => Ok(Self::ExpBrain),
230 0x11 => Ok(Self::Controller),
231 v => Err(DecodeError::new::<Self>(DecodeErrorKind::UnexpectedByte {
232 name: "ProductType",
233 value: v,
234 expected: &[0x10, 0x11, 0x60],
235 })),
236 }
237 }
238}
239
240bitflags! {
241 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
242 pub struct ProductFlags: u8 {
243 const CONNECTED_CABLE = 1 << 0; const CONNECTED_WIRELESS = 1 << 1;
248 }
249}