usb/device/
messages.rs

1// SPDX-FileCopyrightText: 2024 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4#[cfg(keyos)]
5use atsama5d27::udphs::{EndpointDirection, EndpointType};
6use server::{AsScalar, FromScalar};
7
8use super::SetupPacket;
9use crate::error::UsbError;
10
11#[cfg(all(doc, not(keyos)))]
12#[derive(Debug, Clone, Copy, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
13pub enum EndpointType {
14    Control = 0,
15    Isochronous = 1,
16    Bulk = 2,
17    Interrupt = 3,
18}
19
20#[cfg(all(doc, not(keyos)))]
21#[derive(Debug, Clone, Copy, PartialEq, Eq, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
22pub enum EndpointDirection {
23    Out = 0,
24    In = 1,
25}
26
27// === Messages used by higher level drivers ===
28#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
29pub struct SetupPacketCallback(pub SetupPacket);
30
31impl server::BlockingArchive for SetupPacketCallback {
32    type Response = Option<Vec<u8>>;
33}
34
35impl server::MessageId for SetupPacketCallback {
36    const ID: xous::MessageId = 0;
37    const SERVER: &str = "";
38}
39
40// === External messages ===
41
42#[derive(Debug, server::Message, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
43#[response(Result<RegisteredInterfaceInfo, UsbError>)]
44pub struct RegisterInterface {
45    pub interface_number: u8,
46    pub if_class: u8,
47    pub if_subclass: u8,
48    pub if_protocol: u8,
49    pub endpoints: Vec<EndpointProperties>,
50    pub interface_functional_descriptors: Vec<u8>,
51    pub associated_interface_count: u8,
52    pub capabilities: Vec<DeviceCapability>,
53    pub setup_responder: Option<xous::CID>,
54}
55
56#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
57pub struct RegisteredInterfaceInfo {
58    pub endpoints: Vec<u8>,
59}
60
61#[derive(Debug, server::Message)]
62#[response(())]
63pub struct WaitForConnection;
64
65#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
66pub struct EndpointProperties {
67    pub ep_type: EndpointType,
68    pub ep_direction: EndpointDirection,
69    pub max_packet_len: u16,
70    pub interval: u8,
71    /// When `true`, the endpoint uses DMA for data transfer, supporting fragmented reads/writes
72    /// across multiple packets (the hardware reassembles automatically). When `false`, the endpoint
73    /// uses FIFO mode where each read/write operates on a single packet only — the caller must
74    /// ensure the buffer fits within `max_packet_len`.
75    pub use_dma: bool,
76}
77
78#[derive(Debug, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
79pub struct DeviceCapability {
80    pub cap_type: u8,
81    pub cap_subtype: u8,
82    pub cap_uuid: Vec<u8>,
83    pub capability_functional_descriptors: Vec<u8>,
84}
85
86#[derive(Debug, server::Message, Clone)]
87pub struct SetEndpointStalled {
88    pub endpoint: u8,
89    pub stalled: bool,
90}
91
92impl FromScalar<2> for SetEndpointStalled {
93    fn from_scalar(value: [u32; 2]) -> Self { Self { endpoint: value[0] as u8, stalled: value[1] != 0 } }
94}
95
96impl AsScalar<2> for SetEndpointStalled {
97    fn as_scalar(&self) -> [u32; 2] { [self.endpoint as u32, self.stalled as u32] }
98}
99
100#[derive(Debug, server::Message)]
101#[response(Result<usize, UsbError>)]
102pub struct ReadEndpoint {
103    pub buf: xous::MemoryRange,
104    pub endpoint: u8,
105    pub length: u16,
106}
107
108impl From<server::SimpleMemoryMessage> for ReadEndpoint {
109    fn from(msg: server::SimpleMemoryMessage) -> Self {
110        Self { buf: msg.buf, endpoint: msg.arg1 as u8, length: msg.arg2 as u16 }
111    }
112}
113
114impl From<ReadEndpoint> for server::SimpleMemoryMessage {
115    fn from(read: ReadEndpoint) -> Self {
116        Self { buf: read.buf, arg1: read.endpoint as usize, arg2: read.length as usize }
117    }
118}
119
120#[derive(Debug, server::Message)]
121#[response(Result<usize, UsbError>)]
122pub struct WriteEndpoint {
123    pub buf: xous::MemoryRange,
124    pub endpoint: u8,
125    pub length: usize,
126    /// When true, send a ZLP after max_packet_len-aligned transfers to
127    /// signal end-of-transfer to the host.
128    pub zlp: bool,
129}
130
131const ZLP_FLAG: usize = 1 << 31;
132
133impl From<server::SimpleMemoryMessage> for WriteEndpoint {
134    fn from(msg: server::SimpleMemoryMessage) -> Self {
135        Self {
136            buf: msg.buf,
137            endpoint: (msg.arg1 & 0xFF) as u8,
138            zlp: msg.arg1 & ZLP_FLAG != 0,
139            length: msg.arg2,
140        }
141    }
142}
143
144impl From<WriteEndpoint> for server::SimpleMemoryMessage {
145    fn from(val: WriteEndpoint) -> Self {
146        let arg1 = val.endpoint as usize | if val.zlp { ZLP_FLAG } else { 0 };
147        Self { buf: val.buf, arg1, arg2: val.length }
148    }
149}
150
151#[derive(Debug, server::Message, Clone)]
152#[response(bool)]
153pub struct IsDeviceEmulationEnabled;
154
155#[derive(Debug, server::Message, Clone)]
156#[response(bool)]
157pub struct IsDeviceEmulationConnected;
158
159#[derive(Debug, server::Message, Clone)]
160#[response(bool)]
161pub struct IsCableConnected;
162
163#[derive(Debug, server::Message, Clone)]
164#[response(bool)]
165pub struct IsDeviceMode;
166
167#[derive(Debug, server::Message, Clone)]
168#[response(Result<(), UsbError>)]
169pub struct SetVidPid {
170    pub vid: Option<u16>,
171    pub pid: Option<u16>,
172}
173
174impl FromScalar<4> for SetVidPid {
175    fn from_scalar(value: [u32; 4]) -> Self {
176        Self {
177            vid: if value[0] == 0 { None } else { Some(value[0] as u16) },
178            pid: if value[1] == 0 { None } else { Some(value[1] as u16) },
179        }
180    }
181}
182
183impl AsScalar<4> for SetVidPid {
184    fn as_scalar(&self) -> [u32; 4] { [self.vid.unwrap_or(0) as u32, self.pid.unwrap_or(0) as u32, 0, 0] }
185}
186
187#[derive(Debug, server::Message, Clone)]
188#[response(Result<(), UsbError>)]
189pub struct ResetController;
190
191#[derive(Debug, server::Message, Clone)]
192#[response(Result<(), UsbError>)]
193pub struct SetInterfaceEnabled {
194    pub interface_number: u8,
195    pub enabled: bool,
196}
197
198impl FromScalar<2> for SetInterfaceEnabled {
199    fn from_scalar(value: [u32; 2]) -> Self {
200        Self { interface_number: value[0] as u8, enabled: value[1] != 0 }
201    }
202}
203
204impl AsScalar<2> for SetInterfaceEnabled {
205    fn as_scalar(&self) -> [u32; 2] { [self.interface_number as u32, self.enabled as u32] }
206}
207
208impl AsScalar<4> for SetupPacket {
209    fn as_scalar(&self) -> [u32; 4] {
210        [
211            (self.request_type as u32) << 8 | self.request as u32,
212            self.value as u32,
213            self.index as u32,
214            self.length as u32,
215        ]
216    }
217}
218
219impl FromScalar<4> for SetupPacket {
220    fn from_scalar(value: [u32; 4]) -> Self {
221        Self {
222            request_type: (value[0] >> 8) as u8,
223            request: value[0] as u8,
224            value: value[1] as u16,
225            index: value[2] as u16,
226            length: value[3] as u16,
227        }
228    }
229}