258 changes: 243 additions & 15 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,101 @@
//! Dual-licensed under MIT and Apache 2.0. See the [README](../README.md) for
//! more details.

/// Stores the last error from the library. See `bsd_os_errno_set` and
use log::debug;

/// Number of IPC configurations in `NrfxIpcConfig`
const IPC_CONF_NUM: usize = 8;

/// Used by `libmodem` to configure the IPC peripheral. See `nrfx_ipc_config_t`
/// in `nrfx/drivers/include/nrfx_ipc.h`.
#[derive(Debug, Clone)]
pub struct NrfxIpcConfig {
/// Configuration of the connection between signals and IPC channels.
send_task_config: [u32; IPC_CONF_NUM],
/// Configuration of the connection between events and IPC channels.
receive_event_config: [u32; IPC_CONF_NUM],
/// Bitmask with events to be enabled to generate interrupt.
receive_events_enabled: u32,
}

/// IPC callback function type
type NrfxIpcHandler = extern "C" fn(event_mask: u32, ptr: *mut u8);

/// IPC error type
#[repr(u32)]
#[derive(Debug, Copy, Clone)]
pub enum NrfxErr {
///< Operation performed successfully.
Success = 0x0BAD0000,
///< Internal error.
ErrorInternal = (0x0BAD0000 + 1),
///< No memory for operation.
ErrorNoMem = (0x0BAD0000 + 2),
///< Not supported.
ErrorNotSupported = (0x0BAD0000 + 3),
///< Invalid parameter.
ErrorInvalidParam = (0x0BAD0000 + 4),
///< Invalid state, operation disallowed in this state.
ErrorInvalidState = (0x0BAD0000 + 5),
///< Invalid length.
ErrorInvalidLength = (0x0BAD0000 + 6),
///< Operation timed out.
ErrorTimeout = (0x0BAD0000 + 7),
///< Operation is forbidden.
ErrorForbidden = (0x0BAD0000 + 8),
///< Null pointer.
ErrorNull = (0x0BAD0000 + 9),
///< Bad memory address.
ErrorInvalidAddr = (0x0BAD0000 + 10),
///< Busy.
ErrorBusy = (0x0BAD0000 + 11),
///< Module already initialized.
ErrorAlreadyInitialized = (0x0BAD0000 + 12),
}

/// Stores the last error from the library. See `nrf_modem_os_errno_set` and
/// `get_last_error`.
static LAST_ERROR: core::sync::atomic::AtomicI32 = core::sync::atomic::AtomicI32::new(0);

extern "C" {
// This function is in the C library but not in the headers generated by
// nrfxlib-sys.
pub fn IPC_IRQHandler();
}
/// Remembers the IPC interrupt context we were given
static IPC_CONTEXT: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0);

/// Remembers the IPC handler function we were given
static IPC_HANDLER: core::sync::atomic::AtomicUsize = core::sync::atomic::AtomicUsize::new(0);

/// Function required by BSD library. We need to set the EGU1 interrupt.
#[no_mangle]
pub extern "C" fn bsd_os_application_irq_set() {
pub extern "C" fn nrf_modem_os_application_irq_set() {
cortex_m::peripheral::NVIC::pend(crate::cpu::Interrupt::EGU1);
}

/// Function required by BSD library. We need to clear the EGU1 interrupt.
#[no_mangle]
pub extern "C" fn bsd_os_application_irq_clear() {
pub extern "C" fn nrf_modem_os_application_irq_clear() {
cortex_m::peripheral::NVIC::unpend(crate::cpu::Interrupt::EGU1);
}

/// Function required by BSD library. We need to set the EGU2 interrupt.
#[no_mangle]
pub extern "C" fn bsd_os_trace_irq_set() {
pub extern "C" fn nrf_modem_os_trace_irq_set() {
cortex_m::peripheral::NVIC::pend(crate::cpu::Interrupt::EGU2);
}

/// Function required by BSD library. We need to clear the EGU2 interrupt.
#[no_mangle]
pub extern "C" fn bsd_os_trace_irq_clear() {
pub extern "C" fn nrf_modem_os_trace_irq_clear() {
cortex_m::peripheral::NVIC::unpend(crate::cpu::Interrupt::EGU2);
}

/// Function required by BSD library. We have no init to do.
#[no_mangle]
pub extern "C" fn bsd_os_init() {
pub extern "C" fn nrf_modem_os_init() {
// Nothing
}

/// Function required by BSD library. Stores an error code we can read later.
#[no_mangle]
pub extern "C" fn bsd_os_errno_set(errno: i32) {
pub extern "C" fn nrf_modem_os_errno_set(errno: i32) {
LAST_ERROR.store(errno, core::sync::atomic::Ordering::SeqCst);
}

Expand All @@ -61,7 +113,7 @@ pub fn get_last_error() -> i32 {

/// Function required by BSD library
#[no_mangle]
pub extern "C" fn bsd_os_timedwait(_context: u32, p_timeout_ms: *const i32) -> i32 {
pub extern "C" fn nrf_modem_os_timedwait(_context: u32, p_timeout_ms: *const i32) -> i32 {
let timeout_ms = unsafe { *p_timeout_ms };
if timeout_ms < 0 {
// With Zephyr, negative timeouts pend on a semaphore with K_FOREVER.
Expand All @@ -76,13 +128,189 @@ pub extern "C" fn bsd_os_timedwait(_context: u32, p_timeout_ms: *const i32) -> i

/// Function required by BSD library
#[no_mangle]
pub extern "C" fn bsd_os_trace_put(_data: *const u8, _len: u32) -> i32 {
pub extern "C" fn nrf_modem_os_trace_put(_data: *const u8, _len: u32) -> i32 {
// Do nothing
0
}

/// Function required by BSD library
#[no_mangle]
pub extern "C" fn bsd_irrecoverable_error_handler(err: u32) -> ! {
pub extern "C" fn nrf_modem_irrecoverable_error_handler(err: u32) -> ! {
panic!("bsd_irrecoverable_error_handler({})", err);
}

/// The Modem library needs to dynamically allocate memory (a heap) for proper
/// functioning. This memory is used to store the internal data structures that
/// are used to manage the communication between the application core and the
/// modem core. This memory is never shared with the modem core and hence, it
/// can be located anywhere in the application core's RAM instead of the shared
/// memory regions. This function allocates dynamic memory for the library.
#[no_mangle]
pub extern "C" fn nrf_modem_os_alloc(num_bytes_requested: usize) -> *mut u8 {
unsafe { generic_alloc(num_bytes_requested, &crate::LIBRARY_ALLOCATOR) }
}

/// The Modem library needs to dynamically allocate memory (a heap) for proper
/// functioning. This memory is used to store the internal data structures that
/// are used to manage the communication between the application core and the
/// modem core. This memory is never shared with the modem core and hence, it
/// can be located anywhere in the application core's RAM instead of the shared
/// memory regions. This function allocates dynamic memory for the library.
#[no_mangle]
pub extern "C" fn nrf_modem_os_free(ptr: *mut u8) {
unsafe {
generic_free(ptr, &crate::LIBRARY_ALLOCATOR);
}
}

/// Allocate a buffer on the TX area of shared memory.
///
/// @param bytes Buffer size.
/// @return pointer to allocated memory
#[no_mangle]
pub extern "C" fn nrf_modem_os_shm_tx_alloc(num_bytes_requested: usize) -> *mut u8 {
unsafe { generic_alloc(num_bytes_requested, &crate::TX_ALLOCATOR) }
}

/// Free a shared memory buffer in the TX area.
///
/// @param ptr Th buffer to free.
#[no_mangle]
pub extern "C" fn nrf_modem_os_shm_tx_free(ptr: *mut u8) {
unsafe {
generic_free(ptr, &crate::TX_ALLOCATOR);
}
}

/// @brief Function for loading configuration directly into IPC peripheral.
///
/// @param p_config Pointer to the structure with the initial configuration.
#[no_mangle]
pub extern "C" fn nrfx_ipc_config_load(p_config: *const NrfxIpcConfig) {
unsafe {
let config: &NrfxIpcConfig = &*p_config;
debug!("nrfx_ipc_config_load({:?})", config);

let ipc = &(*nrf9160_pac::IPC_NS::ptr());

for (i, value) in config.send_task_config.iter().enumerate() {
ipc.send_cnf[i as usize].write(|w| w.bits(*value));
}

for (i, value) in config.receive_event_config.iter().enumerate() {
ipc.receive_cnf[i as usize].write(|w| w.bits(*value));
}

ipc.intenset
.write(|w| w.bits(config.receive_events_enabled));
}
}

///
/// @brief Function for initializing the IPC driver.
///
/// @param irq_priority Interrupt priority.
/// @param handler Event handler provided by the user. Cannot be NULL.
/// @param p_context Context passed to event handler.
///
/// @retval NRFX_SUCCESS Initialization was successful.
/// @retval NRFX_ERROR_INVALID_STATE Driver is already initialized.
#[no_mangle]
pub extern "C" fn nrfx_ipc_init(
irq_priority: u8,
handler: NrfxIpcHandler,
p_context: usize,
) -> NrfxErr {
use cortex_m::interrupt::InterruptNumber;
let irq = nrf9160_pac::Interrupt::IPC;
let irq_num = usize::from(irq.number());
unsafe {
cortex_m::peripheral::NVIC::unmask(irq);
(*cortex_m::peripheral::NVIC::ptr()).ipr[irq_num].write(irq_priority);
}
IPC_CONTEXT.store(p_context, core::sync::atomic::Ordering::SeqCst);
IPC_HANDLER.store(handler as usize, core::sync::atomic::Ordering::SeqCst);
// Report success
NrfxErr::Success
}

/// Function for uninitializing the IPC module.
#[no_mangle]
pub extern "C" fn nrfx_ipc_uninit() {
unimplemented!();
}

/// Allocate some memory from the given heap.
///
/// We allocate four extra bytes so that we can store the number of bytes
/// requested. This will be needed later when the memory is freed.
///
/// This function is safe to call from an ISR.
unsafe fn generic_alloc(num_bytes_requested: usize, heap: &crate::WrappedHeap) -> *mut u8 {
let sizeof_usize = core::mem::size_of::<usize>();
let mut result = core::ptr::null_mut();
cortex_m::interrupt::free(|cs| {
let num_bytes_allocated = num_bytes_requested + sizeof_usize;
let layout =
core::alloc::Layout::from_size_align_unchecked(num_bytes_allocated, sizeof_usize);
if let Some(ref mut inner_alloc) = *heap.borrow(cs).borrow_mut() {
match inner_alloc.allocate_first_fit(layout) {
Ok(real_block) => {
let real_ptr = real_block.as_ptr();
// We need the block size to run the de-allocation. Store it in the first four bytes.
core::ptr::write_volatile::<usize>(real_ptr as *mut usize, num_bytes_allocated);
// Give them the rest of the block
result = real_ptr.add(sizeof_usize);
}
Err(_e) => {
// Ignore
}
}
}
});
result
}

/// Free some memory back on to the given heap.
///
/// First we must wind the pointer back four bytes to recover the `usize` we
/// stashed during the allocation. We use this to recreate the `Layout` required
/// for the `deallocate` function.
///
/// This function is safe to call from an ISR.
unsafe fn generic_free(ptr: *mut u8, heap: &crate::WrappedHeap) {
let sizeof_usize = core::mem::size_of::<usize>() as isize;
cortex_m::interrupt::free(|cs| {
// Fetch the size from the previous four bytes
let real_ptr = ptr.offset(-sizeof_usize);
let num_bytes_allocated = core::ptr::read_volatile::<usize>(real_ptr as *const usize);
let layout = core::alloc::Layout::from_size_align_unchecked(
num_bytes_allocated,
sizeof_usize as usize,
);
if let Some(ref mut inner_alloc) = *heap.borrow(cs).borrow_mut() {
inner_alloc.deallocate(core::ptr::NonNull::new_unchecked(real_ptr), layout);
}
});
}

/// Call this when we have an IPC IRQ. Not `extern C` as its not called by the
/// library, only our interrupt handler code.
pub unsafe fn ipc_irq_handler() {
// Get the information about events that fired this interrupt
let events_map = (*nrf9160_pac::IPC_NS::ptr()).intpend.read().bits() as u32;

// Clear these events
let mut bitmask = events_map;
while bitmask != 0 {
let event_idx = bitmask.trailing_zeros();
bitmask ^= 1 << event_idx;
(*nrf9160_pac::IPC_NS::ptr()).events_receive[event_idx as usize].write(|w| w.bits(0));
}

// Execute interrupt handler to provide information about events to app
let handler_addr = IPC_HANDLER.load(core::sync::atomic::Ordering::SeqCst);
let handler = core::mem::transmute::<usize, NrfxIpcHandler>(handler_addr);
let context = IPC_CONTEXT.load(core::sync::atomic::Ordering::SeqCst);
(handler)(events_map, context as *mut u8);
}
4 changes: 2 additions & 2 deletions src/gnss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub enum GnssData {
}

/// Specifies which NMEA fields you want from the GNSS sub-system.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct NmeaMask(u16);

/// The specific fields you can enable or disable in an `NmeaMask`.
Expand All @@ -70,7 +70,7 @@ pub enum NmeaField {
}

/// Specifies which non-volatile fields you want to delete before starting the GNSS.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct DeleteMask(u32);

/// The specific fields you can enable or disable in a `DeleteMask`.
Expand Down
130 changes: 103 additions & 27 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
//! # nrfxlib - a Rust library for the nRF9160 interface C library
//!
//! This crate contains wrappers for functions and types defined in Nordic's
//! libbsd, aka nrfxlib.
//! libmodem, which is part of nrfxlib.
//!
//! The `nrfxlib_sys` crate is the auto-generated wrapper for `bsd_os.h` and
//! `nrf_socket.h`. This crate contains Rustic wrappers for those
//! The `nrfxlib_sys` crate is the auto-generated wrapper for `nrf_modem_os.h`
//! and `nrf_socket.h`. This crate contains Rustic wrappers for those
//! auto-generated types.
//!
//! To bring up the LTE stack you need to call `bsd_init()`. Before that you
//! need to enable the EGU1 and EGU2 interrupts, and arrange for the relevant
//! functions (`application_irq_handler` and `trace_irq_handler`
//! respectively) to be called when they occur. You also need to call
//! `IPC_IRQHandler()` when an IPC interrupt occurs.
//! To bring up the LTE stack you need to call `nrf_modem_init()`. Before that
//! you need to enable the EGU1 and EGU2 interrupts, and arrange for the
//! relevant functions (`application_irq_handler` and `trace_irq_handler`
//! respectively) to be called when they occur. The IPC interrupt handler
//! is registered by the relevant callback.
//!
//! To talk to the LTE modem, use the `send_at_command()` function. It will
//! call the callback with the response received from the modem.
//! To talk to the LTE modem, use the `at::send_at_command()` function. It will call
//! the callback with the response received from the modem.
//!
//! To automatically send the AT commands which initialise the modem and wait
//! until it has registered on the network, call the `wait_for_lte()`
//! function. Once that is complete, you can create TCP or TLS sockets and
//! send/receive data.
//! until it has registered on the network, call the `wait_for_lte()` function.
//! Once that is complete, you can create TCP or TLS sockets and send/receive
//! data.
//!
//! Copyright (c) 42 Technology Ltd 2019
//! Copyright (c) 42 Technology Ltd 2021
//!
//! Dual-licensed under MIT and Apache 2.0. See the [README](../README.md) for
//! more details.
Expand Down Expand Up @@ -49,12 +49,15 @@ pub mod udp;
//******************************************************************************

pub use api::*;
pub use ffi::get_last_error;
pub use ffi::{get_last_error, NrfxErr};
pub use raw::{poll, PollEntry, PollFlags, PollResult, Pollable};

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use linked_list_allocator::Heap;
use log::{debug, trace};
use nrfxlib_sys as sys;
use nrf9160_pac as cpu;
use nrfxlib_sys as sys;

//******************************************************************************
// Types
Expand Down Expand Up @@ -109,6 +112,18 @@ pub enum Error {
TooManySockets,
}

/// We need to wrap our heap so it's creatable at run-time and accessible from an ISR.
///
/// * The Mutex allows us to safely share the heap between interrupt routines
/// and the main thread - and nrfxlib will definitely use the heap in an
/// interrupt.
/// * The RefCell lets us share and object and mutate it (but not at the same
/// time)
/// * The Option is because the `linked_list_allocator::empty()` function is not
/// `const` yet and cannot be called here
///
type WrappedHeap = Mutex<RefCell<Option<Heap>>>;

//******************************************************************************
// Constants
//******************************************************************************
Expand All @@ -119,7 +134,16 @@ pub enum Error {
// Global Variables
//******************************************************************************

// None
/// Our general heap.
///
/// We initialise it later with a static variable as the backing store.
static LIBRARY_ALLOCATOR: WrappedHeap = Mutex::new(RefCell::new(None));

/// Our transmit heap.

/// We initalise this later using a special region of shared memory that can be
/// seen by the Cortex-M33 and the modem CPU.
static TX_ALLOCATOR: WrappedHeap = Mutex::new(RefCell::new(None));

//******************************************************************************
// Macros
Expand All @@ -131,20 +155,72 @@ pub enum Error {
// Public Functions and Impl on Public Types
//******************************************************************************

/// Start the BSD library
pub fn init() {
debug!("nrfxlib init");
/// Start the NRF Modem library
pub fn init() -> Result<(), Error> {
unsafe {
/// Allocate some space in global data to use as a heap.
static mut HEAP_MEMORY: [u32; 1024] = [0u32; 1024];
let heap_start = HEAP_MEMORY.as_ptr() as usize;
let heap_size = HEAP_MEMORY.len() * core::mem::size_of::<u32>();
cortex_m::interrupt::free(|cs| {
*LIBRARY_ALLOCATOR.borrow(cs).borrow_mut() = Some(Heap::new(heap_start, heap_size))
});
}

// Tell nrf_modem what memory it can use.
let params = sys::nrf_modem_init_params_t {
shmem: sys::nrf_modem_shmem_cfg {
ctrl: sys::nrf_modem_shmem_cfg__bindgen_ty_1 {
// At start of shared memory (see memory.x)
base: 0x2001_0000,
// This is the amount specified in the NCS 1.5.1 release.
size: 0x0000_04e8,
},
tx: sys::nrf_modem_shmem_cfg__bindgen_ty_2 {
// Follows on from control buffer
base: 0x2001_04e8,
// This is the amount specified in the NCS 1.5.1 release.
size: 0x0000_2000,
},
rx: sys::nrf_modem_shmem_cfg__bindgen_ty_3 {
// Follows on from TX buffer
base: 0x2001_24e8,
// This is the amount specified in the NCS 1.5.1 release.
size: 0x0000_2000,
},
// No trace info
trace: sys::nrf_modem_shmem_cfg__bindgen_ty_4 { base: 0, size: 0 },
},
ipc_irq_prio: 0,
};

unsafe {
sys::bsd_init();
// Use the same TX memory region as above
cortex_m::interrupt::free(|cs| {
*TX_ALLOCATOR.borrow(cs).borrow_mut() = Some(Heap::new(
params.shmem.tx.base as usize,
params.shmem.tx.size as usize,
))
});
}

// OK, let's start the library
let result = unsafe { sys::nrf_modem_init(&params, sys::nrf_modem_mode_t_NORMAL_MODE) };

// Was it happy?
if result < 0 {
Err(Error::Nordic("init", result, ffi::get_last_error()))
} else {
trace!("nrfxlib init complete");
Ok(())
}
trace!("nrfxlib init complete");
}

/// Stop the BSD library
/// Stop the NRF Modem library
pub fn shutdown() {
debug!("nrfxlib shutdown");
unsafe {
sys::bsd_shutdown();
sys::nrf_modem_shutdown();
}
trace!("nrfxlib shutdown complete");
}
Expand All @@ -161,10 +237,10 @@ impl core::fmt::Display for NrfSockAddrIn {
write!(
f,
"{}.{}.{}.{}:{}",
octets[0],
octets[1],
octets[2],
octets[3],
octets[2],
octets[1],
octets[0],
u16::from_be(self.sin_port)
)
}
Expand Down
57 changes: 27 additions & 30 deletions src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ pub(crate) enum SocketDomain {
/// The type of socket (Stream, Datagram, or neither)
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub(crate) enum SocketType {
/// Used with `SocketDomain::Lte`
None,
/// Used with `SocketDomain::Inet` for TCP and TLS streams
Stream,
/// Used with UDP sockets, and for GPS
Expand Down Expand Up @@ -308,32 +306,31 @@ impl<'a> SocketOption<'a> {
}
}

impl Into<i32> for SocketDomain {
fn into(self) -> i32 {
impl From<SocketDomain> for i32 {
fn from(s: SocketDomain) -> i32 {
use SocketDomain::*;
match self {
match s {
Local => sys::NRF_AF_LOCAL as i32,
Lte => sys::NRF_AF_LTE as i32,
Inet => sys::NRF_AF_INET as i32,
}
}
}

impl Into<i32> for SocketType {
fn into(self) -> i32 {
impl From<SocketType> for i32 {
fn from(s: SocketType) -> i32 {
use SocketType::*;
match self {
None => 0,
match s {
Stream => sys::NRF_SOCK_STREAM as i32,
Datagram => sys::NRF_SOCK_DGRAM as i32,
}
}
}

impl Into<i32> for SocketProtocol {
fn into(self) -> i32 {
impl From<SocketProtocol> for i32 {
fn from(s: SocketProtocol) -> i32 {
use SocketProtocol::*;
match self {
match s {
At => sys::NRF_PROTO_AT as i32,
Tcp => sys::NRF_IPPROTO_TCP as i32,
Udp => sys::NRF_IPPROTO_UDP as i32,
Expand Down Expand Up @@ -411,19 +408,19 @@ impl<'a> PollEntry<'a> {
/// let mut socket1 = AtSocket::new();
/// let mut socket2 = GnssSocket::new();
/// let mut poll_list = [
/// PollEntry::new(&mut socket1, PollFlags::Read),
/// PollEntry::new(&mut socket2, PollFlags::Read),
/// PollEntry::new(&mut socket1, PollFlags::Read),
/// PollEntry::new(&mut socket2, PollFlags::Read),
/// ];
/// match nrfxlib::poll(&mut poll_list, 100) {
/// Ok(0) => {
/// // Timeout
/// }
/// Ok(n) => {
/// // One of the sockets is ready. See `poll_list[n].result()`.
/// }
/// Err(e) => {
/// // An error occurred
/// }
/// Ok(0) => {
/// // Timeout
/// }
/// Ok(n) => {
/// // One of the sockets is ready. See `poll_list[n].result()`.
/// }
/// Err(e) => {
/// // An error occurred
/// }
/// }
/// ```
pub fn poll(poll_list: &mut [PollEntry], timeout_ms: u16) -> Result<i32, Error> {
Expand All @@ -434,14 +431,14 @@ pub fn poll(poll_list: &mut [PollEntry], timeout_ms: u16) -> Result<i32, Error>
}

let mut poll_fds: [sys::nrf_pollfd; MAX_SOCKETS_POLL] = [sys::nrf_pollfd {
handle: 0,
requested: 0,
returned: 0,
fd: 0,
events: 0,
revents: 0,
}; MAX_SOCKETS_POLL];

for (poll_entry, pollfd) in poll_list.iter_mut().zip(poll_fds.iter_mut()) {
pollfd.handle = poll_entry.socket.get_fd();
pollfd.requested = poll_entry.flags as i16;
pollfd.fd = poll_entry.socket.get_fd();
pollfd.events = poll_entry.flags as i16;
count += 1;
}

Expand All @@ -452,7 +449,7 @@ pub fn poll(poll_list: &mut [PollEntry], timeout_ms: u16) -> Result<i32, Error>
0 => Ok(0),
n => {
for (poll_entry, pollfd) in poll_list.iter_mut().zip(poll_fds.iter()) {
poll_entry.result = PollResult(pollfd.returned as u32);
poll_entry.result = PollResult(pollfd.revents as u32);
}
Ok(n)
}
Expand All @@ -465,7 +462,7 @@ pub fn poll(poll_list: &mut [PollEntry], timeout_ms: u16) -> Result<i32, Error>

pub(crate) fn htons(input: u16) -> u16 {
let top: u16 = (input >> 8) & 0xFF;
let bottom: u16 = (input >> 0) & 0xFF;
let bottom: u16 = input & 0xFF;
(bottom << 8) | top
}

Expand Down
5 changes: 2 additions & 3 deletions src/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ impl TcpSocket {
debug!("Connecting via TCP to {}:{}", hostname, port);

// Now, make a null-terminated hostname
let mut hostname_smallstring: heapless::String<heapless::consts::U64> =
heapless::String::new();
let mut hostname_smallstring: heapless::String<64> = heapless::String::new();
write!(hostname_smallstring, "{}\0", hostname).map_err(|_| Error::HostnameTooLong)?;
// Now call getaddrinfo with some hints
let hints = sys::nrf_addrinfo {
Expand Down Expand Up @@ -115,7 +114,7 @@ impl TcpSocket {
sin_len: core::mem::size_of::<sys::nrf_sockaddr_in>() as u8,
sin_family: sys::NRF_AF_INET as i32,
sin_port: htons(port),
sin_addr: dns_addr.sin_addr.clone(),
sin_addr: dns_addr.sin_addr,
};

debug!("Trying IP address {}", &crate::NrfSockAddrIn(connect_addr));
Expand Down
5 changes: 2 additions & 3 deletions src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ impl TlsSocket {

let mut result;
// Now, make a null-terminated hostname
let mut hostname_smallstring: heapless::String<heapless::consts::U64> =
heapless::String::new();
let mut hostname_smallstring: heapless::String<64> = heapless::String::new();
write!(hostname_smallstring, "{}\0", hostname).map_err(|_| Error::HostnameTooLong)?;
// Now call getaddrinfo with some hints
let hints = sys::nrf_addrinfo {
Expand Down Expand Up @@ -174,7 +173,7 @@ impl TlsSocket {
sin_len: core::mem::size_of::<sys::nrf_sockaddr_in>() as u8,
sin_family: sys::NRF_AF_INET as i32,
sin_port: htons(port),
sin_addr: dns_addr.sin_addr.clone(),
sin_addr: dns_addr.sin_addr,
};

debug!("Trying IP address {}", &crate::NrfSockAddrIn(connect_addr));
Expand Down
5 changes: 2 additions & 3 deletions src/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ impl UdpSocket {
debug!("Connecting via UDP to {}:{}", hostname, port);

// Now, make a null-terminated hostname
let mut hostname_smallstring: heapless::String<heapless::consts::U64> =
heapless::String::new();
let mut hostname_smallstring: heapless::String<64> = heapless::String::new();
write!(hostname_smallstring, "{}\0", hostname).map_err(|_| Error::HostnameTooLong)?;
// Now call getaddrinfo with some hints
let hints = sys::nrf_addrinfo {
Expand Down Expand Up @@ -119,7 +118,7 @@ impl UdpSocket {
sin_len: core::mem::size_of::<sys::nrf_sockaddr_in>() as u8,
sin_family: sys::NRF_AF_INET as i32,
sin_port: htons(port),
sin_addr: dns_addr.sin_addr.clone(),
sin_addr: dns_addr.sin_addr,
};

debug!("Trying IP address {}", &crate::NrfSockAddrIn(connect_addr));
Expand Down