1use crate::channel::Channel;
2use crate::error::{Error, Result};
3use crate::protocol::nios::NiosPacketError;
4use crate::transport::Transport;
5use nusb::transfer::{Buffer, Bulk, ControlIn, ControlOut, ControlType, In, Out, Recipient};
6use nusb::{Device, Endpoint, Interface, MaybeFuture};
7use std::num::NonZero;
8use std::time::Duration;
9pub const CONTROL_ENDPOINT_OUT: u8 = 0x02;
10pub const CONTROL_ENDPOINT_IN: u8 = 0x82;
11pub const STREAM_ENDPOINT_RX: u8 = 0x81;
12pub const STREAM_ENDPOINT_TX: u8 = 0x01;
13pub const USB_IF_NULL: u8 = 0;
14pub const USB_IF_RF_LINK: u8 = 1;
15pub const BLADE_USB_CMD_RF_RX: u8 = 4;
16pub const BLADE_USB_CMD_RF_TX: u8 = 5;
17pub const BLADE_USB_CMD_SET_LOOPBACK: u8 = 113;
18pub const BLADE_USB_CMD_GET_LOOPBACK: u8 = 114;
19pub const BLADE_USB_CMD_QUERY_DEVICE_READY: u8 = 6;
20pub const BLADE_USB_CMD_RESET: u8 = 105;
21const TIMEOUT: Duration = Duration::from_secs(1);
22#[repr(u8)]
23pub enum StringDescriptors {
24 Manufacturer = 0x1,
25 Product,
26 Serial,
27 Fx3Firmware,
28}
29#[repr(u8)]
30pub enum DescriptorTypes {
31 Configuration = 0x2,
32}
33pub trait DeviceCommands {
34 fn get_supported_languages(&self) -> Result<Vec<u16>>;
35 fn get_configuration_descriptor(&self, descriptor_index: u8) -> Result<Vec<u8>>;
36 fn get_string_descriptor_simple(&self, descriptor_index: NonZero<u8>) -> Result<String>;
37 fn serial(&self) -> Result<String>;
38 fn manufacturer(&self) -> Result<String>;
39 fn product(&self) -> Result<String>;
40}
41impl DeviceCommands for Device {
42 fn get_supported_languages(&self) -> Result<Vec<u16>> {
43 let languages = self
44 .get_string_descriptor_supported_languages(TIMEOUT)
45 .wait()
46 .map_err(|_| Error::Invalid)?
47 .collect();
48 Ok(languages)
49 }
50 fn get_configuration_descriptor(&self, descriptor_index: u8) -> Result<Vec<u8>> {
51 let descriptor = self
52 .get_descriptor(
53 DescriptorTypes::Configuration as u8,
54 descriptor_index,
55 0x00,
56 TIMEOUT,
57 )
58 .wait()
59 .map_err(|_| Error::Invalid)?;
60 Ok(descriptor)
61 }
62 fn get_string_descriptor_simple(&self, descriptor_index: NonZero<u8>) -> Result<String> {
63 let descriptor = self
64 .get_string_descriptor(descriptor_index, 0x409, TIMEOUT)
65 .wait()
66 .map_err(|_| Error::Invalid)?;
67 Ok(descriptor)
68 }
69 fn serial(&self) -> Result<String> {
70 self.get_string_descriptor_simple(
71 NonZero::try_from(StringDescriptors::Serial as u8).map_err(|_| Error::Invalid)?,
72 )
73 }
74 fn manufacturer(&self) -> Result<String> {
75 self.get_string_descriptor_simple(
76 NonZero::try_from(StringDescriptors::Manufacturer as u8).map_err(|_| Error::Invalid)?,
77 )
78 }
79 fn product(&self) -> Result<String> {
80 self.get_string_descriptor_simple(
81 NonZero::try_from(StringDescriptors::Product as u8).map_err(|_| Error::Invalid)?,
82 )
83 }
84}
85pub trait BladeRf1DeviceCommands: DeviceCommands {
86 fn fx3_firmware_version(&self) -> Result<String>;
87}
88impl BladeRf1DeviceCommands for Device {
89 fn fx3_firmware_version(&self) -> Result<String> {
90 self.get_string_descriptor_simple(
91 NonZero::try_from(StringDescriptors::Fx3Firmware as u8).map_err(|_| Error::Invalid)?,
92 )
93 }
94}
95pub trait UsbInterfaceCommands {
96 fn usb_vendor_cmd_int(&self, cmd: u8) -> Result<u32>;
97 fn usb_vendor_cmd_int_wvalue(&self, cmd: u8, wvalue: u16) -> Result<u32>;
98 fn usb_change_setting(&mut self, setting: u8) -> Result<()>;
99 fn usb_set_configuration(&self, configuration: u16) -> Result<()>;
100}
101impl UsbInterfaceCommands for Interface {
102 fn usb_vendor_cmd_int(&self, cmd: u8) -> Result<u32> {
103 let pkt = ControlIn {
104 control_type: ControlType::Vendor,
105 recipient: Recipient::Device,
106 request: cmd,
107 value: 0,
108 index: 0,
109 length: 0x4,
110 };
111 let vec = self.control_in(pkt, TIMEOUT).wait()?;
112 log::debug!("get_vendor_cmd_int response data: {vec:?}");
113 Ok(u32::from_le_bytes(
114 vec.as_slice()[0..4]
115 .try_into()
116 .map_err(|_| Error::Invalid)?,
117 ))
118 }
119 fn usb_vendor_cmd_int_wvalue(&self, cmd: u8, wvalue: u16) -> Result<u32> {
120 let pkt = ControlIn {
121 control_type: ControlType::Vendor,
122 recipient: Recipient::Device,
123 request: cmd,
124 value: wvalue,
125 index: 0,
126 length: 0x4,
127 };
128 let vec = self.control_in(pkt, TIMEOUT).wait()?;
129 log::trace!("vendor_cmd_int_wvalue response data: {vec:?}");
130 Ok(u32::from_le_bytes(
131 vec.as_slice()[0..4]
132 .try_into()
133 .map_err(|_| Error::Invalid)?,
134 ))
135 }
136 fn usb_change_setting(&mut self, setting: u8) -> Result<()> {
137 Ok(self.set_alt_setting(setting).wait()?)
138 }
139 fn usb_set_configuration(&self, configuration: u16) -> Result<()> {
140 Ok(self
141 .control_out(
142 ControlOut {
143 control_type: ControlType::Standard,
144 recipient: Recipient::Device,
145 request: 0x09,
146 value: configuration,
147 index: 0x00,
148 data: &[],
149 },
150 TIMEOUT,
151 )
152 .wait()?)
153 }
154}
155pub trait BladeRf1UsbInterfaceCommands: UsbInterfaceCommands {
156 fn usb_enable_module(&self, channel: Channel, enable: bool) -> Result<()>;
157 fn usb_set_firmware_loopback(&mut self, enable: bool) -> Result<()>;
158 fn usb_get_firmware_loopback(&self) -> Result<bool>;
159 fn usb_device_reset(&self) -> Result<()>;
160 fn usb_is_firmware_ready(&self) -> Result<bool>;
161}
162impl BladeRf1UsbInterfaceCommands for Interface {
163 fn usb_enable_module(&self, channel: Channel, enable: bool) -> Result<()> {
164 let val = enable as u16;
165 let cmd = if channel.is_rx() {
166 BLADE_USB_CMD_RF_RX
167 } else {
168 BLADE_USB_CMD_RF_TX
169 };
170 let _fx3_ret = self.usb_vendor_cmd_int_wvalue(cmd, val)?;
171 Ok(())
172 }
173 fn usb_set_firmware_loopback(&mut self, enable: bool) -> Result<()> {
174 self.usb_vendor_cmd_int_wvalue(BLADE_USB_CMD_SET_LOOPBACK, enable as u16)?;
175 self.usb_change_setting(USB_IF_NULL)?;
176 self.usb_change_setting(USB_IF_RF_LINK)?;
177 Ok(())
178 }
179 fn usb_get_firmware_loopback(&self) -> Result<bool> {
180 let result = self.usb_vendor_cmd_int(BLADE_USB_CMD_GET_LOOPBACK)?;
181 Ok(result != 0)
182 }
183 fn usb_device_reset(&self) -> Result<()> {
184 let pkt = ControlOut {
185 control_type: ControlType::Vendor,
186 recipient: Recipient::Device,
187 request: BLADE_USB_CMD_RESET,
188 value: 0x0,
189 index: 0x0,
190 data: &[],
191 };
192 self.control_out(pkt, TIMEOUT).wait()?;
193 Ok(())
194 }
195 fn usb_is_firmware_ready(&self) -> Result<bool> {
196 Ok(self.usb_vendor_cmd_int(BLADE_USB_CMD_QUERY_DEVICE_READY)? != 0)
197 }
198}
199impl UsbInterfaceCommands for UsbTransport {
200 fn usb_vendor_cmd_int(&self, cmd: u8) -> Result<u32> {
201 self.interface.usb_vendor_cmd_int(cmd)
202 }
203 fn usb_vendor_cmd_int_wvalue(&self, cmd: u8, wvalue: u16) -> Result<u32> {
204 self.interface.usb_vendor_cmd_int_wvalue(cmd, wvalue)
205 }
206 fn usb_change_setting(&mut self, setting: u8) -> Result<()> {
207 self.release_endpoints();
208 self.interface.set_alt_setting(setting).wait()?;
209 Ok(())
210 }
211 fn usb_set_configuration(&self, configuration: u16) -> Result<()> {
212 self.interface.usb_set_configuration(configuration)
213 }
214}
215impl BladeRf1UsbInterfaceCommands for UsbTransport {
216 fn usb_enable_module(&self, channel: Channel, enable: bool) -> Result<()> {
217 self.interface.usb_enable_module(channel, enable)
218 }
219 fn usb_set_firmware_loopback(&mut self, enable: bool) -> Result<()> {
220 self.interface
221 .usb_vendor_cmd_int_wvalue(BLADE_USB_CMD_SET_LOOPBACK, enable as u16)?;
222 self.usb_change_setting(USB_IF_NULL)?;
223 self.usb_change_setting(USB_IF_RF_LINK)?;
224 Ok(())
225 }
226 fn usb_get_firmware_loopback(&self) -> Result<bool> {
227 self.interface.usb_get_firmware_loopback()
228 }
229 fn usb_device_reset(&self) -> Result<()> {
230 self.interface.usb_device_reset()
231 }
232 fn usb_is_firmware_ready(&self) -> Result<bool> {
233 self.interface.usb_is_firmware_ready()
234 }
235}
236struct NiosEndpoints {
237 ep_out: Endpoint<Bulk, Out>,
238 ep_in: Endpoint<Bulk, In>,
239 buf_out: Option<Buffer>,
240 buf_in: Option<Buffer>,
241}
242pub struct UsbTransport {
243 interface: Interface,
244 nios_endpoints: Option<NiosEndpoints>,
245}
246impl UsbTransport {
247 const NIOS_PKT_SIZE: usize = 16;
248 pub fn new(interface: Interface) -> Self {
249 Self {
250 interface,
251 nios_endpoints: None,
252 }
253 }
254 pub fn interface(&self) -> &Interface {
255 &self.interface
256 }
257 pub fn release_endpoints(&mut self) {
258 self.nios_endpoints = None;
259 }
260 fn ensure_nios_endpoints(&mut self) -> Result<&mut NiosEndpoints> {
261 if self.nios_endpoints.is_none() {
262 let ep_out = self
263 .interface
264 .endpoint::<Bulk, Out>(CONTROL_ENDPOINT_OUT)
265 .map_err(|_| Error::EndpointBusy)?;
266 let ep_in = self
267 .interface
268 .endpoint::<Bulk, In>(CONTROL_ENDPOINT_IN)
269 .map_err(|_| Error::EndpointBusy)?;
270 let buf_out = Some(ep_out.allocate(Self::NIOS_PKT_SIZE));
271 let buf_in = Some(ep_in.allocate(ep_in.max_packet_size()));
272 self.nios_endpoints = Some(NiosEndpoints {
273 ep_out,
274 ep_in,
275 buf_out,
276 buf_in,
277 });
278 }
279 Ok(self.nios_endpoints.as_mut().unwrap())
280 }
281 pub fn out_buffer(&mut self) -> Result<&mut [u8]> {
282 Transport::out_buffer(self)
283 }
284 pub fn acquire_streaming_rx_endpoint(&self) -> Result<Endpoint<Bulk, In>> {
285 self.interface
286 .endpoint::<Bulk, In>(STREAM_ENDPOINT_RX)
287 .map_err(|_| Error::EndpointBusy)
288 }
289 pub fn acquire_streaming_tx_endpoint(&self) -> Result<Endpoint<Bulk, Out>> {
290 self.interface
291 .endpoint::<Bulk, Out>(STREAM_ENDPOINT_TX)
292 .map_err(|_| Error::EndpointBusy)
293 }
294}
295impl Transport for UsbTransport {
296 fn out_buffer(&mut self) -> Result<&mut [u8]> {
297 let endpoints = self.ensure_nios_endpoints()?;
298 let buf = endpoints.buf_out.as_mut().ok_or(Error::EndpointBusy)?;
299 buf.clear();
300 buf.extend_fill(Self::NIOS_PKT_SIZE, 0);
301 Ok(buf)
302 }
303 fn submit(&mut self, timeout: Option<Duration>) -> Result<&[u8]> {
304 let endpoints = self.ensure_nios_endpoints()?;
305 let t = timeout.unwrap_or(TIMEOUT);
306 let buf_out = endpoints.buf_out.take().ok_or(Error::EndpointBusy)?;
307 log::trace!("submit: OUT buffer len = {}", buf_out.len());
308 endpoints.ep_out.submit(buf_out);
309 let mut response = endpoints
310 .ep_out
311 .wait_next_complete(t)
312 .ok_or(Error::Timeout)?;
313 response.status?;
314 endpoints.buf_out = Some(response.buffer);
315 let mut buf_in = endpoints.buf_in.take().ok_or(Error::EndpointBusy)?;
316 buf_in.set_requested_len(endpoints.ep_in.max_packet_size());
317 endpoints.ep_in.submit(buf_in);
318 response = endpoints
319 .ep_in
320 .wait_next_complete(t)
321 .ok_or(Error::Timeout)?;
322 response.status?;
323 endpoints.buf_in = Some(response.buffer);
324 let in_buf = endpoints.buf_in.as_ref().unwrap();
325 let in_len = in_buf.len();
326 if in_len < Self::NIOS_PKT_SIZE {
327 return Err(NiosPacketError::InvalidSize(in_len).into());
328 }
329 Ok(&in_buf[..Self::NIOS_PKT_SIZE])
330 }
331}
332impl From<Interface> for UsbTransport {
333 fn from(interface: Interface) -> Self {
334 Self::new(interface)
335 }
336}