diff options
Diffstat (limited to 'libhw')
-rw-r--r-- | libhw/host_alarmclock.c | 68 | ||||
-rw-r--r-- | libhw/host_include/libhw/host_alarmclock.h | 27 | ||||
-rw-r--r-- | libhw/host_include/libhw/host_net.h | 11 | ||||
-rw-r--r-- | libhw/host_net.c | 93 | ||||
-rw-r--r-- | libhw/rp2040_hwspi.c | 13 | ||||
-rw-r--r-- | libhw/rp2040_hwtimer.c | 46 | ||||
-rw-r--r-- | libhw/rp2040_include/libhw/rp2040_hwspi.h | 5 | ||||
-rw-r--r-- | libhw/rp2040_include/libhw/rp2040_hwtimer.h | 7 | ||||
-rw-r--r-- | libhw/rp2040_include/libhw/w5500.h | 18 | ||||
-rw-r--r-- | libhw/w5500.c | 172 | ||||
-rw-r--r-- | libhw/w5500_ll.h | 17 |
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. ***********************************************/ |