Skip to content

Commit ad4d6ee

Browse files
committed
improve internal ergonomics
1 parent 33ebdfa commit ad4d6ee

File tree

4 files changed

+118
-84
lines changed

4 files changed

+118
-84
lines changed

esp32-wroom-rp/src/protocol.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ pub(crate) const MAX_NINA_SMALL_ARRAY_PARAM_BUFFER_LENGTH: usize = 255;
2424
pub(crate) const MAX_NINA_LARGE_ARRAY_PARAM_BUFFER_LENGTH: usize = 1024;
2525

2626
// The maximum length that a 2-byte length NINA response can be
27-
pub(crate) const MAX_NINA_RESPONSE_LENGTH: usize = 1064;
27+
pub(crate) const MAX_NINA_RESPONSE_LENGTH: usize = 1024;
28+
29+
// TODO: unalias this type and turn into a full wrapper struct
30+
/// Provides a byte buffer to hold responses returned from NINA-FW
31+
pub type NinaResponseBuffer = [u8; MAX_NINA_RESPONSE_LENGTH];
2832

2933
#[repr(u8)]
3034
#[derive(Copy, Clone, Debug)]
@@ -400,11 +404,7 @@ pub(crate) trait ProtocolInterface {
400404
) -> Result<(), Error>;
401405
fn stop_client_tcp(&mut self, socket: Socket, _mode: &TransportMode) -> Result<(), Error>;
402406
fn get_client_state_tcp(&mut self, socket: Socket) -> Result<ConnectionState, Error>;
403-
fn send_data(
404-
&mut self,
405-
data: &str,
406-
socket: Socket,
407-
) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error>;
407+
fn send_data(&mut self, data: &str, socket: Socket) -> Result<[u8; 1], Error>;
408408
}
409409

410410
#[derive(Debug)]

esp32-wroom-rp/src/protocol/operation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ impl Operation<NinaAbstractParam> {
2424
// Pushes a new param into the internal `params` Vector which
2525
// builds up an internal byte stream representing one Nina command
2626
// on the data bus.
27-
pub fn param(mut self, param: NinaAbstractParam) -> Self {
27+
pub fn param<P: Into<NinaAbstractParam>>(mut self, param: P) -> Self {
2828
// FIXME: Vec::push() will return T when it is full, handle this gracefully
29-
self.params.push(param).unwrap_or(());
29+
self.params.push(param.into()).unwrap_or(());
3030
self
3131
}
3232
}

esp32-wroom-rp/src/spi.rs

Lines changed: 108 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use super::network::{ConnectionState, IpAddress, NetworkError, Port, Socket, Tra
1515
use super::protocol::operation::Operation;
1616
use super::protocol::{
1717
NinaByteParam, NinaCommand, NinaConcreteParam, NinaLargeArrayParam, NinaParam,
18-
NinaProtocolHandler, NinaSmallArrayParam, NinaWordParam, ProtocolError, ProtocolInterface,
19-
MAX_NINA_PARAMS, MAX_NINA_RESPONSE_LENGTH,
18+
NinaProtocolHandler, NinaResponseBuffer, NinaSmallArrayParam, NinaWordParam, ProtocolError,
19+
ProtocolInterface, MAX_NINA_PARAMS, MAX_NINA_RESPONSE_LENGTH,
2020
};
2121
use super::wifi::ConnectionStatus;
2222
use super::{Error, FirmwareVersion};
@@ -59,12 +59,8 @@ where
5959

6060
fn set_passphrase(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
6161
let operation = Operation::new(NinaCommand::SetPassphrase)
62-
.param(NinaSmallArrayParam::new(ssid).unwrap_or_default().into())
63-
.param(
64-
NinaSmallArrayParam::new(passphrase)
65-
.unwrap_or_default()
66-
.into(),
67-
);
62+
.param(NinaSmallArrayParam::new(ssid)?)
63+
.param(NinaSmallArrayParam::new(passphrase)?);
6864

6965
self.execute(&operation)?;
7066

@@ -85,7 +81,7 @@ where
8581
fn disconnect(&mut self) -> Result<(), Error> {
8682
let dummy_param = NinaByteParam::from_bytes(&[ControlByte::Dummy as u8]);
8783
let operation =
88-
Operation::new(NinaCommand::Disconnect).param(dummy_param.unwrap_or_default().into());
84+
Operation::new(NinaCommand::Disconnect).param(dummy_param.unwrap_or_default());
8985

9086
self.execute(&operation)?;
9187

@@ -98,17 +94,9 @@ where
9894
// FIXME: refactor Operation so it can take different NinaParam types
9995
let operation = Operation::new(NinaCommand::SetDNSConfig)
10096
// FIXME: first param should be able to be a NinaByteParam:
101-
.param(NinaByteParam::from_bytes(&[1]).unwrap_or_default().into())
102-
.param(
103-
NinaSmallArrayParam::from_bytes(&ip1)
104-
.unwrap_or_default()
105-
.into(),
106-
)
107-
.param(
108-
NinaSmallArrayParam::from_bytes(&ip2.unwrap_or_default())
109-
.unwrap_or_default()
110-
.into(),
111-
);
97+
.param(NinaByteParam::from_bytes(&[1])?)
98+
.param(NinaSmallArrayParam::from_bytes(&ip1)?)
99+
.param(NinaSmallArrayParam::from_bytes(&ip2.unwrap_or_default())?);
112100

113101
self.execute(&operation)?;
114102

@@ -118,11 +106,8 @@ where
118106
}
119107

120108
fn req_host_by_name(&mut self, hostname: &str) -> Result<u8, Error> {
121-
let operation = Operation::new(NinaCommand::ReqHostByName).param(
122-
NinaSmallArrayParam::new(hostname)
123-
.unwrap_or_default()
124-
.into(),
125-
);
109+
let operation =
110+
Operation::new(NinaCommand::ReqHostByName).param(NinaSmallArrayParam::new(hostname)?);
126111

127112
self.execute(&operation)?;
128113

@@ -135,7 +120,7 @@ where
135120
Ok(result[0])
136121
}
137122

138-
fn get_host_by_name(&mut self) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
123+
fn get_host_by_name(&mut self) -> Result<NinaResponseBuffer, Error> {
139124
let operation = Operation::new(NinaCommand::GetHostByName);
140125

141126
self.execute(&operation)?;
@@ -182,26 +167,10 @@ where
182167
) -> Result<(), Error> {
183168
let port_as_bytes = [((port & 0xff00) >> 8) as u8, (port & 0xff) as u8];
184169
let operation = Operation::new(NinaCommand::StartClientTcp)
185-
.param(
186-
NinaSmallArrayParam::from_bytes(&ip)
187-
.unwrap_or_default()
188-
.into(),
189-
)
190-
.param(
191-
NinaWordParam::from_bytes(&port_as_bytes)
192-
.unwrap_or_default()
193-
.into(),
194-
)
195-
.param(
196-
NinaByteParam::from_bytes(&[socket])
197-
.unwrap_or_default()
198-
.into(),
199-
)
200-
.param(
201-
NinaByteParam::from_bytes(&[*mode as u8])
202-
.unwrap_or_default()
203-
.into(),
204-
);
170+
.param(NinaSmallArrayParam::from_bytes(&ip)?)
171+
.param(NinaWordParam::from_bytes(&port_as_bytes)?)
172+
.param(NinaByteParam::from_bytes(&[socket])?)
173+
.param(NinaByteParam::from_bytes(&[*mode as u8])?);
205174

206175
self.execute(&operation)?;
207176

@@ -216,11 +185,8 @@ where
216185
// TODO: passing in TransportMode but not using, for now. It will become a way
217186
// of stopping the right kind of client (e.g. TCP, vs UDP)
218187
fn stop_client_tcp(&mut self, socket: Socket, _mode: &TransportMode) -> Result<(), Error> {
219-
let operation = Operation::new(NinaCommand::StopClientTcp).param(
220-
NinaByteParam::from_bytes(&[socket])
221-
.unwrap_or_default()
222-
.into(),
223-
);
188+
let operation =
189+
Operation::new(NinaCommand::StopClientTcp).param(NinaByteParam::from_bytes(&[socket])?);
224190

225191
self.execute(&operation)?;
226192

@@ -233,11 +199,8 @@ where
233199
}
234200

235201
fn get_client_state_tcp(&mut self, socket: Socket) -> Result<ConnectionState, Error> {
236-
let operation = Operation::new(NinaCommand::GetClientStateTcp).param(
237-
NinaByteParam::from_bytes(&[socket])
238-
.unwrap_or_default()
239-
.into(),
240-
);
202+
let operation = Operation::new(NinaCommand::GetClientStateTcp)
203+
.param(NinaByteParam::from_bytes(&[socket])?);
241204

242205
self.execute(&operation)?;
243206

@@ -247,24 +210,16 @@ where
247210
Ok(ConnectionState::from(result[0]))
248211
}
249212

250-
fn send_data(
251-
&mut self,
252-
data: &str,
253-
socket: Socket,
254-
) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
213+
fn send_data(&mut self, data: &str, socket: Socket) -> Result<[u8; 1], Error> {
255214
let operation = Operation::new(NinaCommand::SendDataTcp)
256-
.param(
257-
NinaLargeArrayParam::from_bytes(&[socket])
258-
.unwrap_or_default()
259-
.into(),
260-
)
261-
.param(NinaLargeArrayParam::new(data).unwrap_or_default().into());
215+
.param(NinaLargeArrayParam::from_bytes(&[socket])?)
216+
.param(NinaLargeArrayParam::new(data)?);
262217

263218
self.execute(&operation)?;
264219

265220
let result = self.receive(&operation, 1)?;
266221

267-
Ok(result)
222+
Ok([result[0]])
268223
}
269224
}
270225

@@ -313,7 +268,7 @@ where
313268
&mut self,
314269
operation: &Operation<P>,
315270
expected_num_params: u8,
316-
) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
271+
) -> Result<NinaResponseBuffer, Error> {
317272
self.control_pins.wait_for_esp_select();
318273

319274
self.check_response_ready(&operation.command, expected_num_params)?;
@@ -343,15 +298,14 @@ where
343298
Ok(())
344299
}
345300

346-
fn read_response(&mut self) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
301+
fn read_response(&mut self) -> Result<NinaResponseBuffer, Error> {
347302
let response_length_in_bytes = self.get_byte().ok().unwrap() as usize;
348303

349304
if response_length_in_bytes > MAX_NINA_PARAMS {
350305
return Err(ProtocolError::TooManyParameters.into());
351306
}
352307

353-
let mut response_param_buffer: [u8; MAX_NINA_RESPONSE_LENGTH] =
354-
[0; MAX_NINA_RESPONSE_LENGTH];
308+
let mut response_param_buffer: NinaResponseBuffer = [0; MAX_NINA_RESPONSE_LENGTH];
355309
if response_length_in_bytes > 0 {
356310
response_param_buffer =
357311
self.read_response_bytes(response_param_buffer, response_length_in_bytes)?;
@@ -382,9 +336,9 @@ where
382336

383337
fn read_response_bytes(
384338
&mut self,
385-
mut response_param_buffer: [u8; MAX_NINA_RESPONSE_LENGTH],
339+
mut response_param_buffer: NinaResponseBuffer,
386340
response_length_in_bytes: usize,
387-
) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
341+
) -> Result<NinaResponseBuffer, Error> {
388342
for i in 0..response_length_in_bytes {
389343
response_param_buffer[i] = self.get_byte().ok().unwrap()
390344
}
@@ -452,3 +406,83 @@ where
452406
}
453407
}
454408
}
409+
410+
#[cfg(test)]
411+
mod spi_tests {
412+
use super::*;
413+
414+
use crate::gpio::EspControlPins;
415+
use crate::Error;
416+
use core::cell::RefCell;
417+
use core::str;
418+
use embedded_hal::blocking::spi::Transfer;
419+
use embedded_hal::digital::v2::{InputPin, OutputPin, PinState};
420+
421+
struct TransferMock {}
422+
423+
impl Transfer<u8> for TransferMock {
424+
type Error = Error;
425+
fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Error> {
426+
Ok(words)
427+
}
428+
}
429+
430+
struct OutputPinMock {}
431+
432+
impl OutputPin for OutputPinMock {
433+
type Error = Error;
434+
435+
fn set_low(&mut self) -> Result<(), Self::Error> {
436+
Ok(())
437+
}
438+
439+
fn set_high(&mut self) -> Result<(), Self::Error> {
440+
Ok(())
441+
}
442+
443+
fn set_state(&mut self, _state: PinState) -> Result<(), Self::Error> {
444+
Ok(())
445+
}
446+
}
447+
448+
struct InputPinMock {}
449+
450+
impl InputPin for InputPinMock {
451+
type Error = Error;
452+
453+
fn is_high(&self) -> Result<bool, Self::Error> {
454+
Ok(true)
455+
}
456+
457+
fn is_low(&self) -> Result<bool, Self::Error> {
458+
Ok(true)
459+
}
460+
}
461+
462+
#[test]
463+
fn too_large_of_a_nina_param_throws_error() {
464+
let bytes = [0xA; 256];
465+
let str_slice: &str = str::from_utf8(&bytes).unwrap();
466+
467+
let control_pins = EspControlPins {
468+
cs: OutputPinMock {},
469+
gpio0: OutputPinMock {},
470+
resetn: OutputPinMock {},
471+
ack: InputPinMock {},
472+
};
473+
474+
let transfer_mock = TransferMock {};
475+
476+
let mut protocol_handler = NinaProtocolHandler {
477+
bus: RefCell::new(transfer_mock),
478+
control_pins: control_pins,
479+
};
480+
481+
let result = protocol_handler.set_passphrase(str_slice, "");
482+
483+
assert_eq!(
484+
result.unwrap_err(),
485+
Error::Protocol(ProtocolError::PayloadTooLarge)
486+
)
487+
}
488+
}

esp32-wroom-rp/src/tcp_client.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use super::gpio::EspControlInterface;
5050
use super::network::{
5151
ConnectionState, Hostname, IpAddress, NetworkError, Port, Socket, TransportMode,
5252
};
53-
use super::protocol::{NinaProtocolHandler, ProtocolInterface, MAX_NINA_RESPONSE_LENGTH};
53+
use super::protocol::{NinaProtocolHandler, ProtocolInterface};
5454
use super::wifi::Wifi;
5555
use super::Error;
5656

@@ -176,7 +176,7 @@ where
176176
}
177177

178178
/// Send a string slice of data to a connected server.
179-
pub fn send_data(&mut self, data: &str) -> Result<[u8; MAX_NINA_RESPONSE_LENGTH], Error> {
179+
pub fn send_data(&mut self, data: &str) -> Result<[u8; 1], Error> {
180180
self.protocol_handler
181181
.send_data(data, self.socket.unwrap_or_default())
182182
}

0 commit comments

Comments
 (0)