rdxusb_protocol/
lib.rs

1#![no_std]
2
3use bytemuck::{Pod, Zeroable};
4
5/// In bulk xfer endpoint (has top bit set)
6pub const ENDPOINT_IN: u8 = 0x81;
7/// Out bulk xfer endpoint
8pub const ENDPOINT_OUT: u8 = 0x02;
9
10/// this bit is true on arbitration IDs [`RdxUsbFsPacket::arb_id`] that are extended (29-bit).
11pub const MESSAGE_ARB_ID_EXT: u32 = 0x80000000;
12/// this bit is true on arbitration IDs [`RdxUsbFsPacket::arb_id`] associated with an RTR frame.
13pub const MESSAGE_ARB_ID_RTR: u32 = 0x40000000;
14/// Specifies the frame is specifically addressed to/from the device.
15///
16/// For messages from device to host, this means that the message in fact originates from the device, 
17/// and not any connected devices proxied through other buses.
18///
19/// For messages from host to device, the device will understand that the host message is meant for it,
20/// regardless of any configured device id bits.
21pub const MESSAGE_ARB_ID_DEVICE: u32 = 0x20000000;
22
23
24/// Data packet passed to USB-full-speed devices which have a max packet size of 64.
25#[derive(Debug, PartialEq, Eq, Clone, Copy, Pod, Zeroable)]
26#[repr(C, packed)]
27pub struct RdxUsbFsPacket {
28    /// Timestamp since boot (nanoseconds)
29    pub timestamp_ns: u64,
30    /// CAN arbitration id.
31    pub arb_id: u32, // CAN arbitration id. 
32    /// Data length code.
33    pub dlc: u8,
34    /// Relevant channel. Zero most of the time.
35    pub channel: u8,
36    /// Misc flags (unused for now)
37    pub flags: u16,
38    /// data (max size: 48 bytes)
39    pub data: [u8; 48]
40}
41
42/// Generic data packet passed to/from RdxUsb APIs.
43#[derive(Debug, Copy, Clone, PartialEq, Eq, Pod, Zeroable)]
44#[repr(C, packed)]
45pub struct RdxUsbPacket {
46    /// Timestamp since boot (nanoseconds)
47    pub timestamp_ns: u64,
48    /// CAN arbitration id.
49    pub arb_id: u32, // CAN arbitration id. 
50    /// Data length code.
51    pub dlc: u8,
52    /// Relevant channel. Zero most of the time.
53    pub channel: u8,
54    /// Misc flags (unused for now)
55    pub flags: u16,
56    /// data (max size: 64 bytes)
57    pub data: [u8; 64]
58}
59
60impl From<RdxUsbFsPacket> for RdxUsbPacket {
61    fn from(value: RdxUsbFsPacket) -> Self {
62        let mut data = [0u8; 64];
63        data[..48].copy_from_slice(&value.data);
64        Self {
65            timestamp_ns: value.timestamp_ns,
66            arb_id: value.arb_id,
67            dlc: value.dlc,
68            channel: value.channel,
69            flags: value.flags,
70            data,
71        }
72    }
73}
74
75impl TryFrom<RdxUsbPacket> for RdxUsbFsPacket {
76    type Error = RdxUsbPacket;
77
78    fn try_from(value: RdxUsbPacket) -> Result<Self, Self::Error> {
79        if value.dlc > 48 { return Err(value); }
80        let len = value.dlc as usize;
81        let mut data = [0u8; 48];
82        data[..len].copy_from_slice(&value.data[..len]);
83        Ok(RdxUsbFsPacket {
84            timestamp_ns: value.timestamp_ns,
85            arb_id: value.arb_id,
86            dlc: value.dlc,
87            channel: value.channel,
88            flags: value.flags,
89            data,
90        })
91        
92    }
93}
94
95impl RdxUsbFsPacket {
96    /// The message arbitration id
97    pub const fn id(&self) -> u32 {
98        self.arb_id & 0x1fff_ffff
99    }
100
101    /// Does the packet use extended (29-bit) IDs?
102    pub const fn extended(&self) -> bool {
103        self.arb_id & MESSAGE_ARB_ID_EXT != 0
104    }
105
106    /// Is the packet an RTR packet?
107    pub const fn rtr(&self) -> bool {
108        self.arb_id & MESSAGE_ARB_ID_RTR != 0
109    }
110
111    /// Is the packet a device packet?
112    pub const fn device(&self) -> bool {
113        self.arb_id & MESSAGE_ARB_ID_DEVICE != 0
114    }
115
116    /// Should always be 64.
117    pub const SIZE: usize = core::mem::size_of::<Self>();
118
119    pub fn encode(&self) -> &[u8; Self::SIZE] {
120        bytemuck::cast_ref(self)
121    }
122
123    pub fn from_buf(buf: [u8; Self::SIZE]) -> Self {
124        bytemuck::cast(buf)
125    }
126}
127
128impl RdxUsbPacket {
129    /// The message arbitration id
130    pub const fn id(&self) -> u32 {
131        self.arb_id & 0x1fff_ffff
132    }
133
134    /// Does the packet use extended (29-bit) IDs?
135    pub const fn extended(&self) -> bool {
136        self.arb_id & MESSAGE_ARB_ID_EXT != 0
137    }
138
139    /// Is the packet an RTR packet?
140    pub const fn rtr(&self) -> bool {
141        self.arb_id & MESSAGE_ARB_ID_RTR != 0
142    }
143
144    /// Is the packet a device packet?
145    pub const fn device(&self) -> bool {
146        self.arb_id & MESSAGE_ARB_ID_DEVICE != 0
147    }
148
149    /// Should always be 64.
150    pub const SIZE: usize = core::mem::size_of::<Self>();
151
152    pub fn into_array(self) -> [u8; Self::SIZE] {
153        unsafe { core::mem::transmute(self) }
154    }
155
156    pub fn from_buf(buf: [u8; Self::SIZE]) -> Self {
157        unsafe { core::mem::transmute(buf) }
158    }
159}
160
161/// Struct returned by the device info control request
162#[derive(Debug, PartialEq, Eq, Clone, Copy, Pod, Zeroable)]
163#[repr(C, packed)]
164pub struct RdxUsbDeviceInfo {
165    /// The SKU index of the device (the first number in the serial)
166    pub sku: u16,
167    /// The interface index that the RdxUSB interface uses
168    pub interface_idx: u8,
169    /// The number of channels that the RdxUSB interface supports (0-indexed)
170    pub n_channels: u8,
171    /// The major protocol version
172    pub protocol_version_major: u16,
173    /// The minor protocol version
174    pub protocol_version_minor: u16,
175    /// Reserved bits
176    pub reserved: [u8; 24]
177}
178
179impl RdxUsbDeviceInfo {
180    /// Should always be 32.
181    pub const SIZE: usize = core::mem::size_of::<Self>();
182
183    pub fn encode(&self) -> &[u8; Self::SIZE] {
184        bytemuck::cast_ref(self)
185    }
186
187    pub fn from_buf(buf: [u8; Self::SIZE]) -> Self {
188        bytemuck::cast(buf)
189    }
190}
191
192/// Control requests supported
193#[derive(Debug, PartialEq, Eq, Clone, Copy)]
194#[repr(u8)]
195pub enum RdxUsbCtrl {
196    DeviceInfo = 0,
197}
198
199/// USB-Full Speed protocol version
200pub const PROTOCOL_VERSION_MAJOR_FS: u16 = 1;