summaryrefslogtreecommitdiff
path: root/libhw
diff options
context:
space:
mode:
Diffstat (limited to 'libhw')
-rw-r--r--libhw/host_alarmclock.c68
-rw-r--r--libhw/host_include/libhw/host_alarmclock.h27
-rw-r--r--libhw/host_include/libhw/host_net.h11
-rw-r--r--libhw/host_net.c93
-rw-r--r--libhw/rp2040_hwspi.c13
-rw-r--r--libhw/rp2040_hwtimer.c46
-rw-r--r--libhw/rp2040_include/libhw/rp2040_hwspi.h5
-rw-r--r--libhw/rp2040_include/libhw/rp2040_hwtimer.h7
-rw-r--r--libhw/rp2040_include/libhw/w5500.h18
-rw-r--r--libhw/w5500.c172
-rw-r--r--libhw/w5500_ll.h17
11 files changed, 158 insertions, 319 deletions
diff --git a/libhw/host_alarmclock.c b/libhw/host_alarmclock.c
index 5f7e494..19ece7c 100644
--- a/libhw/host_alarmclock.c
+++ b/libhw/host_alarmclock.c
@@ -1,62 +1,27 @@
/* libhw/host_alarmclock.c - <libhw/generic/alarmclock.h> implementation for POSIX hosts
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <errno.h>
#include <error.h>
#include <signal.h>
-#include <time.h>
#include <libcr/coroutine.h>
#include <libmisc/assert.h>
-#include <libmisc/vcall.h>
#define IMPLEMENTATION_FOR_LIBHW_GENERIC_ALARMCLOCK_H YES
#include <libhw/generic/alarmclock.h>
+#define IMPLEMENTATION_FOR_LIBHW_HOST_ALARMCLOCK_H YES
+#include <libhw/host_alarmclock.h>
+
#include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_ns_time() */
-/* Types **********************************************************************/
-
-struct hostclock {
- implements_alarmclock;
- bool initialized;
- clockid_t clock_id;
- timer_t timer_id;
- struct alarmclock_trigger *queue;
-};
-
-/* Globals ********************************************************************/
-
-static uint64_t hostclock_get_time_ns(implements_alarmclock *self);
-static bool hostclock_add_trigger(implements_alarmclock *self,
- struct alarmclock_trigger *trigger,
- uint64_t fire_at_ns,
- void (*cb)(void *),
- void *cb_arg);
-static void hostclock_del_trigger(implements_alarmclock *self,
- struct alarmclock_trigger *trigger);
-
-static struct alarmclock_vtable hostclock_vtable = {
- .get_time_ns = hostclock_get_time_ns,
- .add_trigger = hostclock_add_trigger,
- .del_trigger = hostclock_del_trigger,
-};
-
-static struct hostclock clock_monotonic = {
- .vtable = &hostclock_vtable,
- .clock_id = CLOCK_MONOTONIC,
-};
-
-implements_alarmclock *bootclock = &clock_monotonic;
-
-/* Main implementation ********************************************************/
-
-static uint64_t hostclock_get_time_ns(implements_alarmclock *_alarmclock) {
- struct hostclock *alarmclock =
- VCALL_SELF(struct hostclock, implements_alarmclock, _alarmclock);
+LO_IMPLEMENTATION_C(alarmclock, struct hostclock, hostclock, static)
+
+static uint64_t hostclock_get_time_ns(struct hostclock *alarmclock) {
assert(alarmclock);
struct timespec ts;
@@ -91,13 +56,11 @@ static void hostclock_handle_sig_alarm(int LM_UNUSED(sig), siginfo_t *info, void
}
}
-static bool hostclock_add_trigger(implements_alarmclock *_alarmclock,
- struct alarmclock_trigger *trigger,
- uint64_t fire_at_ns,
- void (*cb)(void *),
- void *cb_arg) {
- struct hostclock *alarmclock =
- VCALL_SELF(struct hostclock, implements_alarmclock, _alarmclock);
+static bool hostclock_add_trigger(struct hostclock *alarmclock,
+ struct alarmclock_trigger *trigger,
+ uint64_t fire_at_ns,
+ void (*cb)(void *),
+ void *cb_arg) {
assert(alarmclock);
assert(trigger);
assert(fire_at_ns);
@@ -148,11 +111,8 @@ static bool hostclock_add_trigger(implements_alarmclock *_alarmclock,
return false;
}
-static void hostclock_del_trigger(implements_alarmclock *_alarmclock,
- struct alarmclock_trigger *trigger) {
- struct hostclock *alarmclock =
- VCALL_SELF(struct hostclock, implements_alarmclock, _alarmclock);
-
+static void hostclock_del_trigger(struct hostclock *alarmclock,
+ struct alarmclock_trigger *trigger) {
assert(alarmclock);
assert(trigger);
diff --git a/libhw/host_include/libhw/host_alarmclock.h b/libhw/host_include/libhw/host_alarmclock.h
new file mode 100644
index 0000000..89df68a
--- /dev/null
+++ b/libhw/host_include/libhw/host_alarmclock.h
@@ -0,0 +1,27 @@
+/* libhw/host_alarmclock.h - <libhw/generic/alarmclock.h> implementation for hosted glibc
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBHW_HOST_ALARMCLOCK_H_
+#define _LIBHW_HOST_ALARMCLOCK_H_
+
+#include <stdbool.h> /* for bool */
+#include <time.h> /* for clockid_t, timer_t */
+
+#include <libmisc/private.h>
+#include <libhw/generic/alarmclock.h>
+
+struct hostclock {
+ clockid_t clock_id;
+
+ BEGIN_PRIVATE(LIBHW_HOST_ALARMCLOCK_H)
+ bool initialized;
+ timer_t timer_id;
+ struct alarmclock_trigger *queue;
+ END_PRIVATE(LIBHW_HOST_ALARMCLOCK_H)
+};
+LO_IMPLEMENTATION_H(alarmclock, struct hostclock, hostclock)
+
+#endif /* _LIBHW_HOST_ALARMCLOCK_H_ */
diff --git a/libhw/host_include/libhw/host_net.h b/libhw/host_include/libhw/host_net.h
index bfef5c9..fced229 100644
--- a/libhw/host_include/libhw/host_net.h
+++ b/libhw/host_include/libhw/host_net.h
@@ -1,6 +1,6 @@
/* libhw/host_net.h - <libhw/generic/net.h> implementation for hosted glibc
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -14,33 +14,30 @@
#include <libhw/generic/net.h>
struct _hostnet_tcp_conn {
- implements_net_stream_conn;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
uint64_t read_deadline_ns;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp)
struct hostnet_tcp_listener {
- implements_net_stream_listener;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
struct _hostnet_tcp_conn active_conn;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist)
void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port);
struct hostnet_udp_conn {
- implements_net_packet_conn;
-
BEGIN_PRIVATE(LIBHW_HOST_NET_H)
int fd;
uint64_t read_deadline_ns;
END_PRIVATE(LIBHW_HOST_NET_H)
};
+LO_IMPLEMENTATION_H(net_packet_conn, struct hostnet_udp_conn, hostnet_udp)
void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port);
diff --git a/libhw/host_net.c b/libhw/host_net.c
index bf79480..505c7dc 100644
--- a/libhw/host_net.c
+++ b/libhw/host_net.c
@@ -21,7 +21,7 @@
#include <libcr/coroutine.h>
#include <libmisc/assert.h>
#include <libmisc/macro.h>
-#include <libmisc/vcall.h>
+#include <libobj/obj.h>
#include <libhw/generic/alarmclock.h>
@@ -30,6 +30,10 @@
#include "host_util.h" /* for host_sigrt_alloc(), ns_to_host_us_time() */
+LO_IMPLEMENTATION_C(net_stream_conn, struct _hostnet_tcp_conn, hostnet_tcp, static)
+LO_IMPLEMENTATION_C(net_stream_listener, struct hostnet_tcp_listener, hostnet_tcplist, static)
+LO_IMPLEMENTATION_C(net_packet_conn, struct hostnet_udp_conn, hostnet_udp, static)
+
/* common *********************************************************************/
static int hostnet_sig_io = 0;
@@ -109,25 +113,6 @@ static inline ssize_t hostnet_map_negerrno(ssize_t v, enum hostnet_timeout_op op
/* TCP init() ( AKA socket(3) + listen(3) )************************************/
-static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_listener *);
-static int hostnet_tcplist_close(implements_net_stream_listener *);
-static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *conn, uint64_t ts_ns);
-static ssize_t hostnet_tcp_read(implements_net_stream_conn *conn, void *buf, size_t count);
-static ssize_t hostnet_tcp_write(implements_net_stream_conn *conn, void *buf, size_t count);
-static int hostnet_tcp_close(implements_net_stream_conn *conn, bool rd, bool wr);
-
-static struct net_stream_listener_vtable hostnet_tcp_listener_vtable = {
- .accept = hostnet_tcplist_accept,
- .close = hostnet_tcplist_close,
-};
-
-static struct net_stream_conn_vtable hostnet_tcp_conn_vtable = {
- .set_read_deadline = hostnet_tcp_set_read_deadline,
- .read = hostnet_tcp_read,
- .write = hostnet_tcp_write,
- .close = hostnet_tcp_close,
-};
-
void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port) {
int listenerfd;
union {
@@ -151,7 +136,6 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port)
if (listen(listenerfd, 0) < 0)
error(1, errno, "listen(fd=%d)", listenerfd);
- self->vtable = &hostnet_tcp_listener_vtable;
self->fd = listenerfd;
}
@@ -175,9 +159,7 @@ static void *hostnet_pthread_accept(void *_args) {
return NULL;
}
-static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_listener *_listener) {
- struct hostnet_tcp_listener *listener =
- VCALL_SELF(struct hostnet_tcp_listener, implements_net_stream_listener, _listener);
+static lo_interface net_stream_conn hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) {
assert(listener);
int ret_connfd;
@@ -188,22 +170,19 @@ static implements_net_stream_conn *hostnet_tcplist_accept(implements_net_stream_
.ret_connfd = &ret_connfd,
};
if (RUN_PTHREAD(hostnet_pthread_accept, &args))
- return NULL;
+ return LO_NULL(net_stream_conn);
if (ret_connfd < 0)
- return NULL;
+ return LO_NULL(net_stream_conn);
- listener->active_conn.vtable = &hostnet_tcp_conn_vtable;
listener->active_conn.fd = ret_connfd;
listener->active_conn.read_deadline_ns = 0;
- return &listener->active_conn;
+ return lo_box_hostnet_tcp_as_net_stream_conn(&listener->active_conn);
}
/* TCP listener close() *******************************************************/
-static int hostnet_tcplist_close(implements_net_stream_listener *_listener) {
- struct hostnet_tcp_listener *listener =
- VCALL_SELF(struct hostnet_tcp_listener, implements_net_stream_listener, _listener);
+static int hostnet_tcplist_close(struct hostnet_tcp_listener *listener) {
assert(listener);
return hostnet_map_negerrno(shutdown(listener->fd, SHUT_RDWR) ? -errno : 0, OP_NONE);
@@ -211,9 +190,7 @@ static int hostnet_tcplist_close(implements_net_stream_listener *_listener) {
/* TCP read() *****************************************************************/
-static void hostnet_tcp_set_read_deadline(implements_net_stream_conn *_conn, uint64_t ts_ns) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static void hostnet_tcp_set_read_deadline(struct _hostnet_tcp_conn *conn, uint64_t ts_ns) {
assert(conn);
conn->read_deadline_ns = ts_ns;
@@ -250,9 +227,7 @@ static void *hostnet_pthread_read(void *_args) {
return NULL;
}
-static ssize_t hostnet_tcp_read(implements_net_stream_conn *_conn, void *buf, size_t count) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static ssize_t hostnet_tcp_read(struct _hostnet_tcp_conn *conn, void *buf, size_t count) {
assert(conn);
ssize_t ret;
@@ -267,7 +242,7 @@ static ssize_t hostnet_tcp_read(implements_net_stream_conn *_conn, void *buf, si
.ret = &ret,
};
if (conn->read_deadline_ns) {
- uint64_t now_ns = VCALL(bootclock, get_time_ns);
+ uint64_t now_ns = LO_CALL(bootclock, get_time_ns);
if (conn->read_deadline_ns < now_ns)
return -NET_ERECV_TIMEOUT;
args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns);
@@ -310,9 +285,7 @@ static void *hostnet_pthread_write(void *_args) {
return NULL;
}
-static ssize_t hostnet_tcp_write(implements_net_stream_conn *_conn, void *buf, size_t count) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static ssize_t hostnet_tcp_write(struct _hostnet_tcp_conn *conn, void *buf, size_t count) {
assert(conn);
ssize_t ret;
@@ -333,9 +306,7 @@ static ssize_t hostnet_tcp_write(implements_net_stream_conn *_conn, void *buf, s
/* TCP close() ****************************************************************/
-static int hostnet_tcp_close(implements_net_stream_conn *_conn, bool rd, bool wr) {
- struct _hostnet_tcp_conn *conn =
- VCALL_SELF(struct _hostnet_tcp_conn, implements_net_stream_conn, _conn);
+static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn, bool rd, bool wr) {
assert(conn);
int how;
@@ -352,21 +323,6 @@ static int hostnet_tcp_close(implements_net_stream_conn *_conn, bool rd, bool wr
/* UDP init() *****************************************************************/
-static void hostnet_udp_set_read_deadline(implements_net_packet_conn *self,
- uint64_t ts_ns);
-static ssize_t hostnet_udp_sendto(implements_net_packet_conn *self, void *buf, size_t len,
- struct net_ip4_addr addr, uint16_t port);
-static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *self, void *buf, size_t len,
- struct net_ip4_addr *ret_addr, uint16_t *ret_port);
-static int hostnet_udp_close(implements_net_packet_conn *self);
-
-static struct net_packet_conn_vtable hostnet_udp_conn_vtable = {
- .set_read_deadline = hostnet_udp_set_read_deadline,
- .sendto = hostnet_udp_sendto,
- .recvfrom = hostnet_udp_recvfrom,
- .close = hostnet_udp_close,
-};
-
void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
int fd;
union {
@@ -385,7 +341,6 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
if (bind(fd, &addr.gen, sizeof addr) < 0)
error(1, errno, "bind");
- self->vtable = &hostnet_udp_conn_vtable;
self->fd = fd;
self->read_deadline_ns = 0;
}
@@ -427,10 +382,8 @@ static void *hostnet_pthread_sendto(void *_args) {
return NULL;
}
-static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf, size_t count,
+static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count,
struct net_ip4_addr node, uint16_t port) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
ssize_t ret;
@@ -453,10 +406,8 @@ static ssize_t hostnet_udp_sendto(implements_net_packet_conn *_conn, void *buf,
/* UDP recvfrom() *************************************************************/
-static void hostnet_udp_set_read_deadline(implements_net_packet_conn *_conn,
+static void hostnet_udp_set_read_deadline(struct hostnet_udp_conn *conn,
uint64_t ts_ns) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
conn->read_deadline_ns = ts_ns;
@@ -514,10 +465,8 @@ static void *hostnet_pthread_recvfrom(void *_args) {
return NULL;
}
-static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf, size_t count,
+static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count,
struct net_ip4_addr *ret_node, uint16_t *ret_port) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
assert(conn);
ssize_t ret;
@@ -534,7 +483,7 @@ static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf
.ret_port = ret_port,
};
if (conn->read_deadline_ns) {
- uint64_t now_ns = VCALL(bootclock, get_time_ns);
+ uint64_t now_ns = LO_CALL(bootclock, get_time_ns);
if (conn->read_deadline_ns < now_ns)
return -NET_ERECV_TIMEOUT;
args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns);
@@ -549,9 +498,7 @@ static ssize_t hostnet_udp_recvfrom(implements_net_packet_conn *_conn, void *buf
/* UDP close() ****************************************************************/
-static int hostnet_udp_close(implements_net_packet_conn *_conn) {
- struct hostnet_udp_conn *conn =
- VCALL_SELF(struct hostnet_udp_conn, implements_net_packet_conn, _conn);
+static int hostnet_udp_close(struct hostnet_udp_conn *conn) {
assert(conn);
return hostnet_map_negerrno(close(conn->fd) ? -errno : 0, OP_NONE);
diff --git a/libhw/rp2040_hwspi.c b/libhw/rp2040_hwspi.c
index 47dfc97..23f3e8c 100644
--- a/libhw/rp2040_hwspi.c
+++ b/libhw/rp2040_hwspi.c
@@ -1,6 +1,6 @@
/* libhw/rp2040_hwspi.c - <libhw/generic/spi.h> implementation for the RP2040's ARM Primecell SSP (PL022)
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -8,16 +8,11 @@
#include <hardware/gpio.h> /* pico-sdk:hardware_gpio */
#include <libmisc/assert.h>
-#include <libmisc/vcall.h>
#define IMPLEMENTATION_FOR_LIBHW_RP2040_HWSPI_H YES
#include <libhw/rp2040_hwspi.h>
-static void rp2040_hwspi_readwritev(implements_spi *, const struct bidi_iovec *iov, int iovcnt);
-
-struct spi_vtable rp2040_hwspi_vtable = {
- .readwritev = rp2040_hwspi_readwritev,
-};
+LO_IMPLEMENTATION_C(spi, struct rp2040_hwspi, rp2040_hwspi, static)
void _rp2040_hwspi_init(struct rp2040_hwspi *self,
enum rp2040_hwspi_instance inst_num,
@@ -84,13 +79,11 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self,
gpio_put(pin_cs, 1);
/* Return. */
- self->vtable = &rp2040_hwspi_vtable;
self->inst = inst;
self->pin_cs = pin_cs;
}
-static void rp2040_hwspi_readwritev(implements_spi *_self, const struct bidi_iovec *iov, int iovcnt) {
- struct rp2040_hwspi *self = VCALL_SELF(struct rp2040_hwspi, implements_spi, _self);
+static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct bidi_iovec *iov, int iovcnt) {
assert(self);
spi_inst_t *inst = self->inst;
diff --git a/libhw/rp2040_hwtimer.c b/libhw/rp2040_hwtimer.c
index c8c281e..ada6246 100644
--- a/libhw/rp2040_hwtimer.c
+++ b/libhw/rp2040_hwtimer.c
@@ -1,6 +1,6 @@
/* libhw/rp2040_hwtimer.c - <libhw/generic/alarmclock.h> implementation for the RP2040's hardware timer
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -9,10 +9,10 @@
#include <libcr/coroutine.h>
#include <libmisc/assert.h>
-#include <libmisc/vcall.h>
#define IMPLEMENTATION_FOR_LIBHW_GENERIC_ALARMCLOCK_H YES
#include <libhw/generic/alarmclock.h>
+
#include <libhw/rp2040_hwtimer.h>
/******************************************************************************/
@@ -23,48 +23,32 @@ void add_alarm_at(void) {};
/* Types **********************************************************************/
struct rp2040_hwtimer {
- implements_alarmclock;
enum rp2040_hwalarm_instance alarm_num;
bool initialized;
struct alarmclock_trigger *queue;
};
+LO_IMPLEMENTATION_H(alarmclock, struct rp2040_hwtimer, rp2040_hwtimer);
+LO_IMPLEMENTATION_C(alarmclock, struct rp2040_hwtimer, rp2040_hwtimer, static);
/* Globals ********************************************************************/
-static uint64_t rp2040_hwtimer_get_time_ns(implements_alarmclock *self);
-static bool rp2040_hwtimer_add_trigger(implements_alarmclock *self,
- struct alarmclock_trigger *trigger,
- uint64_t fire_at_ns,
- void (*cb)(void *),
- void *cb_arg);
-static void rp2040_hwtimer_del_trigger(implements_alarmclock *self,
- struct alarmclock_trigger *trigger);
-
-static struct alarmclock_vtable rp2040_hwtimer_vtable = {
- .get_time_ns = rp2040_hwtimer_get_time_ns,
- .add_trigger = rp2040_hwtimer_add_trigger,
- .del_trigger = rp2040_hwtimer_del_trigger,
-};
-
static struct rp2040_hwtimer hwtimers[] = {
- { .vtable = &rp2040_hwtimer_vtable, .alarm_num = 0 },
- { .vtable = &rp2040_hwtimer_vtable, .alarm_num = 1 },
- { .vtable = &rp2040_hwtimer_vtable, .alarm_num = 2 },
- { .vtable = &rp2040_hwtimer_vtable, .alarm_num = 3 },
+ { .alarm_num = 0 },
+ { .alarm_num = 1 },
+ { .alarm_num = 2 },
+ { .alarm_num = 3 },
};
static_assert(sizeof(hwtimers)/sizeof(hwtimers[0]) == _RP2040_HWALARM_NUM);
-implements_alarmclock *bootclock = &hwtimers[0];
-
/* Main implementation ********************************************************/
-implements_alarmclock *rp2040_hwtimer(enum rp2040_hwalarm_instance alarm_num) {
+lo_interface alarmclock rp2040_hwtimer(enum rp2040_hwalarm_instance alarm_num) {
assert(alarm_num < _RP2040_HWALARM_NUM);
- return &hwtimers[alarm_num];
+ return lo_box_rp2040_hwtimer_as_alarmclock(&hwtimers[alarm_num]);
}
-static uint64_t rp2040_hwtimer_get_time_ns(implements_alarmclock *) {
+static uint64_t rp2040_hwtimer_get_time_ns(struct rp2040_hwtimer *) {
return timer_time_us_64(timer_hw) * (NS_PER_S/US_PER_S);
}
@@ -93,13 +77,11 @@ static void rp2040_hwtimer_intrhandler(void) {
timer_hw->alarm[alarm_num] = (uint32_t)NS_TO_US_ROUNDUP(alarmclock->queue->fire_at_ns);
}
-static bool rp2040_hwtimer_add_trigger(implements_alarmclock *_alarmclock,
+static bool rp2040_hwtimer_add_trigger(struct rp2040_hwtimer *alarmclock,
struct alarmclock_trigger *trigger,
uint64_t fire_at_ns,
void (*cb)(void *),
void *cb_arg) {
- struct rp2040_hwtimer *alarmclock =
- VCALL_SELF(struct rp2040_hwtimer, implements_alarmclock, _alarmclock);
assert(alarmclock);
assert(trigger);
assert(fire_at_ns);
@@ -149,10 +131,8 @@ static bool rp2040_hwtimer_add_trigger(implements_alarmclock *_alarmclock,
return false;
}
-static void rp2040_hwtimer_del_trigger(implements_alarmclock *_alarmclock,
+static void rp2040_hwtimer_del_trigger(struct rp2040_hwtimer *alarmclock,
struct alarmclock_trigger *trigger) {
- struct rp2040_hwtimer *alarmclock =
- VCALL_SELF(struct rp2040_hwtimer, implements_alarmclock, _alarmclock);
assert(alarmclock);
assert(trigger);
diff --git a/libhw/rp2040_include/libhw/rp2040_hwspi.h b/libhw/rp2040_include/libhw/rp2040_hwspi.h
index 7c4991b..b1abe0c 100644
--- a/libhw/rp2040_include/libhw/rp2040_hwspi.h
+++ b/libhw/rp2040_include/libhw/rp2040_hwspi.h
@@ -1,6 +1,6 @@
/* libhw/rp2040_hwspi.h - <libhw/generic/spi.h> implementation for the RP2040's ARM Primecell SSP (PL022)
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -19,13 +19,12 @@ enum rp2040_hwspi_instance {
};
struct rp2040_hwspi {
- implements_spi;
-
BEGIN_PRIVATE(LIBHW_RP2040_HWSPI_H)
void /*spi_inst_t*/ *inst;
uint pin_cs;
END_PRIVATE(LIBHW_RP2040_HWSPI_H)
};
+LO_IMPLEMENTATION_H(spi, struct rp2040_hwspi, rp2040_hwspi)
/**
* Initialize an instance of `struct rp2040_hwspi`.
diff --git a/libhw/rp2040_include/libhw/rp2040_hwtimer.h b/libhw/rp2040_include/libhw/rp2040_hwtimer.h
index 6710ab1..40e4172 100644
--- a/libhw/rp2040_include/libhw/rp2040_hwtimer.h
+++ b/libhw/rp2040_include/libhw/rp2040_hwtimer.h
@@ -1,6 +1,6 @@
/* libhw/rp2040_hwtimer.h - <libhw/generic/alarmclock.h> implementation for the RP2040's hardware timer
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -10,8 +10,7 @@
#include <libhw/generic/alarmclock.h>
/**
- * The RP2040 has one system "timer" (which we also use for
- * ./rp2040_bootclock.c) with 4 alarm interrupts.
+ * The RP2040 has one system "timer" with 4 alarm interrupts.
*/
enum rp2040_hwalarm_instance {
RP2040_HWALARM_0 = 0,
@@ -21,6 +20,6 @@ enum rp2040_hwalarm_instance {
_RP2040_HWALARM_NUM,
};
-implements_alarmclock *rp2040_hwtimer(enum rp2040_hwalarm_instance alarm_num);
+lo_interface alarmclock rp2040_hwtimer(enum rp2040_hwalarm_instance alarm_num);
#endif /* _LIBHW_RP2040_HWTIMER_H_ */
diff --git a/libhw/rp2040_include/libhw/w5500.h b/libhw/rp2040_include/libhw/w5500.h
index 3cae620..ab9f50e 100644
--- a/libhw/rp2040_include/libhw/w5500.h
+++ b/libhw/rp2040_include/libhw/w5500.h
@@ -1,6 +1,6 @@
/* libhw/w5500.h - <libhw/generic/net.h> implementation for the WIZnet W5500 chip
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -20,11 +20,8 @@
CR_CHAN_DECLARE(_w5500_sockintr_ch, uint8_t)
struct _w5500_socket {
- /* const-after-init */
- implements_net_stream_listener implements_net_stream_listener;
- implements_net_stream_conn implements_net_stream_conn;
- implements_net_packet_conn implements_net_packet_conn;
BEGIN_PRIVATE(LIBHW_W5500_H)
+ /* const-after-init */
uint8_t socknum;
/* mutable */
@@ -43,12 +40,14 @@ struct _w5500_socket {
END_PRIVATE(LIBHW_W5500_H)
};
+LO_IMPLEMENTATION_H(net_stream_listener, struct _w5500_socket, w5500_tcplist)
+LO_IMPLEMENTATION_H(net_stream_conn, struct _w5500_socket, w5500_tcp)
+LO_IMPLEMENTATION_H(net_packet_conn, struct _w5500_socket, w5500_udp)
struct w5500 {
- /* const-after-init */
- implements_net_iface;
BEGIN_PRIVATE(LIBHW_W5500_H)
- implements_spi *spidev;
+ /* const-after-init */
+ lo_interface spi spidev;
uint pin_intr;
uint pin_reset;
struct net_eth_addr hwaddr;
@@ -61,6 +60,7 @@ struct w5500 {
cr_mutex_t mu;
END_PRIVATE(LIBHW_W5500_H)
};
+LO_IMPLEMENTATION_H(net_iface, struct w5500, w5500_if)
/**
* Initialize a WIZnet W5500 Ethernet-and-TCP/IP-offload chip.
@@ -82,7 +82,7 @@ struct w5500 {
_w5500_init(self, spi, pin_intr, pin_reset, eth_addr); \
} while (0)
void _w5500_init(struct w5500 *self,
- implements_spi *spi, uint pin_intr, uint pin_reset,
+ lo_interface spi spi, uint pin_intr, uint pin_reset,
struct net_eth_addr addr);
/**
diff --git a/libhw/w5500.c b/libhw/w5500.c
index cebcf8e..dfe169f 100644
--- a/libhw/w5500.c
+++ b/libhw/w5500.c
@@ -1,6 +1,6 @@
/* libhw/w5500.c - <libhw/generic/net.h> implementation for the WIZnet W5500 chip
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@@ -74,7 +74,6 @@
#include <hardware/gpio.h> /* pico-sdk:hardware_gpio */
#include <libcr/coroutine.h> /* for cr_yield() */
-#include <libmisc/vcall.h> /* for VCALL_SELF() */
#include <libhw/generic/alarmclock.h> /* for sleep_*() */
@@ -124,61 +123,12 @@ static const char *w5500_state_str(uint8_t state) {
}
}
-/* vtables ********************************************************************/
-
-/* iface */
-static struct net_eth_addr w5500_if_hwaddr (implements_net_iface *);
-static void w5500_if_up (implements_net_iface *, struct net_iface_config);
-static void w5500_if_down (implements_net_iface *);
-static implements_net_stream_listener *w5500_if_tcp_listen (implements_net_iface *, uint16_t local_port);
-static implements_net_stream_conn *w5500_if_tcp_dial (implements_net_iface *, struct net_ip4_addr, uint16_t remote_port);
-static implements_net_packet_conn *w5500_if_udp_conn (implements_net_iface *, uint16_t local_port);
-
-/* stream_listener */
-static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_listener *);
-static int w5500_tcplist_close (implements_net_stream_listener *);
-
-/* stream_conn */
-static void w5500_tcp_set_read_deadline (implements_net_stream_conn *, uint64_t ns);
-static ssize_t w5500_tcp_read (implements_net_stream_conn *, void *, size_t);
-static ssize_t w5500_tcp_write (implements_net_stream_conn *, void *, size_t);
-static int w5500_tcp_close (implements_net_stream_conn *, bool rd, bool wr);
-
-/* packet_conn */
-static void w5500_udp_set_read_deadline (implements_net_packet_conn *, uint64_t ns);
-static ssize_t w5500_udp_recvfrom (implements_net_packet_conn *, void *, size_t, struct net_ip4_addr *, uint16_t *);
-static ssize_t w5500_udp_sendto (implements_net_packet_conn *, void *, size_t, struct net_ip4_addr, uint16_t);
-static int w5500_udp_close (implements_net_packet_conn *);
-
-/* tables */
-
-static struct net_iface_vtable w5500_iface_vtable = {
- .hwaddr = w5500_if_hwaddr,
- .ifup = w5500_if_up,
- .ifdown = w5500_if_down,
- .tcp_listen = w5500_if_tcp_listen,
- .tcp_dial = w5500_if_tcp_dial,
- .udp_conn = w5500_if_udp_conn,
-};
-
-static struct net_stream_listener_vtable w5500_tcp_listener_vtable = {
- .accept = w5500_tcplist_accept,
- .close = w5500_tcplist_close,
-};
-
-static struct net_stream_conn_vtable w5500_tcp_conn_vtable = {
- .set_read_deadline = w5500_tcp_set_read_deadline,
- .read = w5500_tcp_read,
- .write = w5500_tcp_write,
- .close = w5500_tcp_close,
-};
-
-static struct net_packet_conn_vtable w5500_udp_conn_vtable = {
- .set_read_deadline = w5500_udp_set_read_deadline,
- .recvfrom = w5500_udp_recvfrom,
- .sendto = w5500_udp_sendto,
- .close = w5500_udp_close,
-};
+/* libobj *********************************************************************/
+
+LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static)
+LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static)
+LO_IMPLEMENTATION_C(net_packet_conn, struct _w5500_socket, w5500_udp, static)
+LO_IMPLEMENTATION_C(net_iface, struct w5500, w5500_if, static)
/* mid-level utilities ********************************************************/
@@ -311,9 +261,6 @@ static inline void w5500_socket_close(struct _w5500_socket *socket) {
}
#define ASSERT_SELF(_iface, _mode) \
- struct _w5500_socket *socket = \
- VCALL_SELF(struct _w5500_socket, \
- implements_net_##_iface, _socket); \
assert(socket); \
uint8_t socknum = socket->socknum; \
assert(socknum < 8); \
@@ -333,15 +280,14 @@ static void w5500_intrhandler(uint gpio, uint32_t LM_UNUSED(event_mask)) {
}
void _w5500_init(struct w5500 *chip,
- implements_spi *spi, uint pin_intr, uint pin_reset,
+ lo_interface spi spi, uint pin_intr, uint pin_reset,
struct net_eth_addr addr) {
assert(chip);
- assert(spi);
+ assert(!LO_IS_NULL(spi));
/* Initialize the data structures. */
*chip = (struct w5500){
/* const-after-init */
- .implements_net_iface = { .vtable = &w5500_iface_vtable },
.spidev = spi,
.pin_intr = pin_intr,
.pin_reset = pin_reset,
@@ -353,9 +299,6 @@ void _w5500_init(struct w5500 *chip,
for (uint8_t i = 0; i < 8; i++) {
chip->sockets[i] = (struct _w5500_socket){
/* const-after-init */
- .implements_net_stream_listener = { .vtable = &w5500_tcp_listener_vtable },
- .implements_net_stream_conn = { .vtable = &w5500_tcp_conn_vtable },
- .implements_net_packet_conn = { .vtable = &w5500_udp_conn_vtable },
.socknum = i,
/* mutable */
.next_free = (i + 1 < 8) ? &chip->sockets[i+1] : NULL,
@@ -449,15 +392,13 @@ void w5500_soft_reset(struct w5500 *chip) {
cr_mutex_unlock(&chip->mu);
}
-static struct net_eth_addr w5500_if_hwaddr(implements_net_iface *_chip) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static struct net_eth_addr w5500_if_hwaddr(struct w5500 *chip) {
assert(chip);
return chip->hwaddr;
}
-static void _w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static void _w5500_if_up(struct w5500 *chip, struct net_iface_config cfg) {
assert(chip);
cr_mutex_lock(&chip->mu);
@@ -469,27 +410,26 @@ static void _w5500_if_up(implements_net_iface *_chip, struct net_iface_config cf
cr_mutex_unlock(&chip->mu);
}
-static void w5500_if_up(implements_net_iface *_chip, struct net_iface_config cfg) {
+static void w5500_if_ifup(struct w5500 *chip, struct net_iface_config cfg) {
debugf("if_up()");
debugf(":: addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.addr));
debugf(":: gateway_addr = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.gateway_addr));
debugf(":: subnet_mask = "PRI_net_ip4_addr, ARG_net_ip4_addr(cfg.subnet_mask));
- _w5500_if_up(_chip, cfg);
+ _w5500_if_up(chip, cfg);
}
-static void w5500_if_down(implements_net_iface *_chip) {
+static void w5500_if_ifdown(struct w5500 *chip) {
debugf("if_down()");
- _w5500_if_up(_chip, (struct net_iface_config){0});
+ _w5500_if_up(chip, (struct net_iface_config){0});
}
-static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface *_chip, uint16_t local_port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_stream_listener w5500_if_tcp_listen(struct w5500 *chip, uint16_t local_port) {
assert(chip);
struct _w5500_socket *sock = w5500_alloc_socket(chip);
if (!sock) {
debugf("tcp_listen() => no sock");
- return NULL;
+ return LO_NULL(net_stream_listener);
}
debugf("tcp_listen() => sock[%"PRIu8"]", sock->socknum);
@@ -502,12 +442,11 @@ static implements_net_stream_listener *w5500_if_tcp_listen(implements_net_iface
sock->read_deadline_ns = 0;
sock->list_open = true;
- return &sock->implements_net_stream_listener;
+ return lo_box_w5500_tcplist_as_net_stream_listener(sock);
}
-static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip,
- struct net_ip4_addr node, uint16_t port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip,
+ struct net_ip4_addr node, uint16_t port) {
assert(chip);
assert(memcmp(node.octets, net_ip4_addr_zero.octets, 4));
assert(memcmp(node.octets, net_ip4_addr_broadcast.octets, 4));
@@ -516,7 +455,7 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
struct _w5500_socket *socket = w5500_alloc_socket(chip);
if (!socket) {
debugf("tcp_dial() => no sock");
- return NULL;
+ return LO_NULL(net_stream_conn);
}
uint8_t socknum = socket->socknum;
debugf("tcp_dial() => sock[%"PRIu8"]", socknum);
@@ -553,21 +492,20 @@ static implements_net_stream_conn *w5500_if_tcp_dial(implements_net_iface *_chip
cr_yield();
break;
case STATE_TCP_ESTABLISHED:
- return &socket->implements_net_stream_conn;
+ return lo_box_w5500_tcp_as_net_stream_conn(socket);
default:
goto restart;
}
}
}
-static implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip, uint16_t local_port) {
- struct w5500 *chip = VCALL_SELF(struct w5500, implements_net_iface, _chip);
+static lo_interface net_packet_conn w5500_if_udp_conn(struct w5500 *chip, uint16_t local_port) {
assert(chip);
struct _w5500_socket *socket = w5500_alloc_socket(chip);
if (!socket) {
debugf("udp_conn() => no sock");
- return NULL;
+ return LO_NULL(net_packet_conn);
}
uint8_t socknum = socket->socknum;
debugf("udp_conn() => sock[%"PRIu8"]", socknum);
@@ -590,18 +528,18 @@ static implements_net_packet_conn *w5500_if_udp_conn(implements_net_iface *_chip
cr_yield();
cr_mutex_unlock(&chip->mu);
- return &socket->implements_net_packet_conn;
+ return lo_box_w5500_udp_as_net_packet_conn(socket);
}
/* tcp_listener methods *******************************************************/
-static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_listener *_socket) {
+static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *socket) {
ASSERT_SELF(stream_listener, TCP);
restart:
if (!socket->list_open) {
debugf("tcp_listener.accept() => already closed");
- return NULL;
+ return LO_NULL(net_stream_conn);
}
cr_mutex_lock(&chip->mu);
@@ -630,14 +568,14 @@ static implements_net_stream_conn *w5500_tcplist_accept(implements_net_stream_li
/* fall-through */
case STATE_TCP_CLOSE_WAIT:
socket->write_open = true;
- return &socket->implements_net_stream_conn;
+ return lo_box_w5500_tcp_as_net_stream_conn(socket);
default:
goto restart;
}
}
}
-static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
+static int w5500_tcplist_close(struct _w5500_socket *socket) {
debugf("tcp_listener.close()");
ASSERT_SELF(stream_listener, TCP);
@@ -648,7 +586,7 @@ static int w5500_tcplist_close(implements_net_stream_listener *_socket) {
/* tcp_conn methods ***********************************************************/
-static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, size_t count) {
+static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t count) {
debugf("tcp_conn.write(%zu)", count);
ASSERT_SELF(stream_conn, TCP);
assert(buf);
@@ -725,7 +663,7 @@ static ssize_t w5500_tcp_write(implements_net_stream_conn *_socket, void *buf, s
return done;
}
-static void w5500_tcp_set_read_deadline(implements_net_stream_conn *_socket, uint64_t ns) {
+static void w5500_tcp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
debugf("tcp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(stream_conn, TCP);
socket->read_deadline_ns = ns;
@@ -736,7 +674,7 @@ static void w5500_tcp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, size_t count) {
+static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t count) {
debugf("tcp_conn.read()");
ASSERT_SELF(stream_conn, TCP);
assert(buf);
@@ -744,21 +682,21 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
struct alarmclock_trigger trigger = {0};
if (socket->read_deadline_ns)
- VCALL(bootclock, add_trigger, &trigger,
- socket->read_deadline_ns,
- w5500_tcp_alarm_handler,
- socket);
+ LO_CALL(bootclock, add_trigger, &trigger,
+ socket->read_deadline_ns,
+ w5500_tcp_alarm_handler,
+ socket);
/* Wait until there is data to read. */
uint16_t avail = 0;
for (;;) {
if (!socket->read_open) {
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
debugf(" => soft closed");
return -NET_ECLOSED;
}
- if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
- VCALL(bootclock, del_trigger, &trigger);
+ if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) {
+ LO_CALL(bootclock, del_trigger, &trigger);
debugf(" => recv timeout");
return -NET_ERECV_TIMEOUT;
}
@@ -770,7 +708,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
case STATE_TCP_FIN_WAIT:
break; /* OK */
default:
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
debugf(" => hard closed");
return -NET_ECLOSED;
@@ -781,7 +719,7 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
/* We have data to read. */
break;
if (state == STATE_TCP_CLOSE_WAIT) {
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
debugf(" => EOF");
return 0;
@@ -801,12 +739,12 @@ static ssize_t w5500_tcp_read(implements_net_stream_conn *_socket, void *buf, si
w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+avail));
w5500_socket_cmd(socket, CMD_RECV);
/* Return. */
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
return avail;
}
-static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr) {
+static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) {
debugf("tcp_conn.close(rd=%s, wr=%s)", rd ? "true" : "false", wr ? "true" : "false");
ASSERT_SELF(stream_conn, TCP);
@@ -839,7 +777,7 @@ static int w5500_tcp_close(implements_net_stream_conn *_socket, bool rd, bool wr
/* udp_conn methods ***********************************************************/
-static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf, size_t count,
+static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
struct net_ip4_addr node, uint16_t port) {
debugf("udp_conn.sendto()");
ASSERT_SELF(packet_conn, UDP);
@@ -896,7 +834,7 @@ static ssize_t w5500_udp_sendto(implements_net_packet_conn *_socket, void *buf,
}
}
-static void w5500_udp_set_read_deadline(implements_net_packet_conn *_socket, uint64_t ns) {
+static void w5500_udp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
debugf("udp_conn.set_read_deadline(%"PRIu64")", ns);
ASSERT_SELF(packet_conn, UDP);
socket->read_deadline_ns = ns;
@@ -907,7 +845,7 @@ static void w5500_udp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf, size_t count,
+static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_t count,
struct net_ip4_addr *ret_node, uint16_t *ret_port) {
debugf("udp_conn.recvfrom()");
ASSERT_SELF(packet_conn, UDP);
@@ -916,23 +854,23 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
struct alarmclock_trigger trigger = {0};
if (socket->read_deadline_ns)
- VCALL(bootclock, add_trigger, &trigger,
- socket->read_deadline_ns,
- w5500_udp_alarm_handler,
- socket);
+ LO_CALL(bootclock, add_trigger, &trigger,
+ socket->read_deadline_ns,
+ w5500_udp_alarm_handler,
+ socket);
/* Wait until there is data to read. */
uint16_t avail = 0;
for (;;) {
- if (socket->read_deadline_ns && socket->read_deadline_ns <= VCALL(bootclock, get_time_ns)) {
- VCALL(bootclock, del_trigger, &trigger);
+ if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) {
+ LO_CALL(bootclock, del_trigger, &trigger);
debugf(" => recv timeout");
return -NET_ERECV_TIMEOUT;
}
cr_mutex_lock(&chip->mu);
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
if (state != STATE_UDP) {
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
debugf(" => hard closed");
return -NET_ECLOSED;
}
@@ -970,12 +908,12 @@ static ssize_t w5500_udp_recvfrom(implements_net_packet_conn *_socket, void *buf
w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+8+len));
w5500_socket_cmd(socket, CMD_RECV);
/* Return. */
- VCALL(bootclock, del_trigger, &trigger);
+ LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
return len;
}
-static int w5500_udp_close(implements_net_packet_conn *_socket) {
+static int w5500_udp_close(struct _w5500_socket *socket) {
debugf("udp_conn.close()");
ASSERT_SELF(packet_conn, UDP);
diff --git a/libhw/w5500_ll.h b/libhw/w5500_ll.h
index 25aa6b5..92d9f14 100644
--- a/libhw/w5500_ll.h
+++ b/libhw/w5500_ll.h
@@ -3,7 +3,7 @@
* Based entirely on the W5500 datasheet, v1.1.0.
* https://docs.wiznet.io/img/products/w5500/W5500_ds_v110e.pdf
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -15,10 +15,9 @@
#include <libmisc/assert.h> /* for assert(), static_assert() */
#include <libmisc/endian.h> /* for uint16be_t */
-#include <libmisc/vcall.h> /* for VCALL() */
#include <libhw/generic/net.h> /* for struct net_eth_addr, struct net_ip4_addr */
-#include <libhw/generic/spi.h> /* for implements_spi */
+#include <libhw/generic/spi.h> /* for lo_interface spi */
/* Config *********************************************************************/
@@ -74,8 +73,8 @@ _w5500ll_write(const char *func,
#else
w5500ll_write(
#endif
- implements_spi *spidev, uint16_t addr, uint8_t block, void *data, size_t data_len) {
- assert(spidev);
+ lo_interface spi spidev, uint16_t addr, uint8_t block, void *data, size_t data_len) {
+ assert(!LO_IS_NULL(spidev));
assert((block & ~CTL_MASK_BLOCK) == 0);
assert(data);
assert(data_len);
@@ -94,7 +93,7 @@ w5500ll_write(
{.iov_read_dst = NULL, .iov_write_src = header, .iov_len = sizeof(header)},
{.iov_read_dst = NULL, .iov_write_src = data, .iov_len = data_len},
};
- VCALL(spidev, readwritev, iov, 2);
+ LO_CALL(spidev, readwritev, iov, 2);
}
static inline void
@@ -104,8 +103,8 @@ _w5500ll_read(const char *func,
#else
w5500ll_read(
#endif
- implements_spi *spidev, uint16_t addr, uint8_t block, void *data, size_t data_len) {
- assert(spidev);
+ lo_interface spi spidev, uint16_t addr, uint8_t block, void *data, size_t data_len) {
+ assert(!LO_IS_NULL(spidev));
assert((block & ~CTL_MASK_BLOCK) == 0);
assert(data);
assert(data_len);
@@ -124,7 +123,7 @@ w5500ll_read(
{.iov_read_dst = NULL, .iov_write_src = header, .iov_len = sizeof(header)},
{.iov_read_dst = data, .iov_write_src = NULL, .iov_len = data_len},
};
- VCALL(spidev, readwritev, iov, 2);
+ LO_CALL(spidev, readwritev, iov, 2);
}
/* Common chip-wide registers. ***********************************************/