summaryrefslogtreecommitdiff
path: root/libhw_cr
diff options
context:
space:
mode:
Diffstat (limited to 'libhw_cr')
-rw-r--r--libhw_cr/host_alarmclock.c15
-rw-r--r--libhw_cr/host_net.c259
-rw-r--r--libhw_cr/host_util.c99
-rw-r--r--libhw_cr/host_util.h6
-rw-r--r--libhw_cr/rp2040_hwspi.c3
-rw-r--r--libhw_cr/rp2040_hwtimer.c2
-rw-r--r--libhw_cr/w5500.c88
7 files changed, 317 insertions, 155 deletions
diff --git a/libhw_cr/host_alarmclock.c b/libhw_cr/host_alarmclock.c
index ac2093c..325f7e0 100644
--- a/libhw_cr/host_alarmclock.c
+++ b/libhw_cr/host_alarmclock.c
@@ -5,9 +5,12 @@
*/
#include <errno.h>
-#include <error.h>
#include <signal.h>
+#define error __error
+#include <error.h>
+#undef error
+
#include <libcr/coroutine.h>
#include <libmisc/assert.h>
@@ -27,7 +30,7 @@ static uint64_t hostclock_get_time_ns(struct hostclock *alarmclock) {
struct timespec ts;
if (clock_gettime(alarmclock->clock_id, &ts) != 0)
- error(1, errno, "clock_gettime(%d)", (int)alarmclock->clock_id);
+ __error(1, errno, "clock_gettime(%d)", (int)alarmclock->clock_id);
return ns_from_host_ns_time(ts);
}
@@ -52,7 +55,7 @@ static void hostclock_handle_sig_alarm(int LM_UNUSED(sig), siginfo_t *info, void
.it_interval = {},
};
if (timer_settime(alarmclock->timer_id, TIMER_ABSTIME, &alarmspec, NULL) != 0)
- error(1, errno, "timer_settime");
+ __error(1, errno, "timer_settime");
}
}
@@ -93,9 +96,9 @@ static bool hostclock_add_trigger(struct hostclock *alarmclock,
.sa_sigaction = hostclock_handle_sig_alarm,
};
if (sigaction(how_to_notify.sigev_signo, &action, NULL) != 0)
- error(1, errno, "sigaction");
+ __error(1, errno, "sigaction");
if (timer_create(alarmclock->clock_id, &how_to_notify, &alarmclock->timer_id) != 0)
- error(1, errno, "timer_create(%d)", (int)alarmclock->clock_id);
+ __error(1, errno, "timer_create(%d)", (int)alarmclock->clock_id);
alarmclock->initialized = true;
}
if (alarmclock->queue == trigger) {
@@ -104,7 +107,7 @@ static bool hostclock_add_trigger(struct hostclock *alarmclock,
.it_interval = {},
};
if (timer_settime(alarmclock->timer_id, TIMER_ABSTIME, &alarmspec, NULL) != 0)
- error(1, errno, "timer_settime");
+ __error(1, errno, "timer_settime");
}
cr_restore_interrupts(saved);
diff --git a/libhw_cr/host_net.c b/libhw_cr/host_net.c
index 8016787..39bfd46 100644
--- a/libhw_cr/host_net.c
+++ b/libhw_cr/host_net.c
@@ -7,7 +7,9 @@
#define _GNU_SOURCE /* for pthread_sigqueue(3gnu) */
/* misc */
#include <errno.h> /* for errno, EAGAIN, EINVAL */
+#define error __error
#include <error.h> /* for error(3gnu) */
+#undef error
#include <stdlib.h> /* for abs(), shutdown(), SHUT_RD, SHUT_WR, SHUT_RDWR */
#include <unistd.h> /* for read(), write() */
/* net */
@@ -63,7 +65,7 @@ static void hostnet_init(void) {
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = hostnet_handle_sig_io;
if (sigaction(hostnet_sig_io, &action, NULL) < 0)
- error(1, errno, "sigaction");
+ __error(1, errno, "sigaction");
}
#define WAKE_COROUTINE(args) do { \
@@ -78,46 +80,47 @@ static void hostnet_init(void) {
} while (r == EAGAIN); \
} while (0)
-static inline bool RUN_PTHREAD(void *(*fn)(void *), void *args) {
+static inline host_errno_t RUN_PTHREAD(void *(*fn)(void *), void *args) {
pthread_t thread;
+ host_errno_t r;
bool saved = cr_save_and_disable_interrupts();
- if (pthread_create(&thread, NULL, fn, args))
- return true;
+ r = pthread_create(&thread, NULL, fn, args);
+ if (r) {
+ cr_restore_interrupts(saved);
+ return r;
+ }
cr_pause_and_yield();
cr_restore_interrupts(saved);
- if (pthread_join(thread, NULL))
- return true;
- return false;
+ return pthread_join(thread, NULL);
}
enum hostnet_timeout_op {
- OP_NONE,
+ OP_CLOSE,
OP_SEND,
OP_RECV,
};
-static inline ssize_t hostnet_map_negerrno(ssize_t v, enum hostnet_timeout_op op) {
- if (v >= 0)
- return v;
- switch (v) {
- case -EHOSTUNREACH:
- return -NET_EARP_TIMEOUT;
- case -ETIMEDOUT:
+static inline error hostnet_error(host_errno_t errnum, enum hostnet_timeout_op op) {
+ assert(errnum > 0);
+ switch (errnum) {
+ case EHOSTUNREACH:
+ return error_new(E_NET_EARP_TIMEOUT);
+ case ETIMEDOUT:
switch (op) {
- case OP_NONE:
+ case OP_CLOSE:
assert_notreached("impossible ETIMEDOUT");
case OP_SEND:
- return -NET_EACK_TIMEOUT;
+ return error_new(E_NET_EACK_TIMEOUT);
case OP_RECV:
- return -NET_ERECV_TIMEOUT;
+ return error_new(E_NET_ERECV_TIMEOUT);
}
assert_notreached("invalid timeout op");
- case -EBADF:
- return -NET_ECLOSED;
- case -EMSGSIZE:
- return -NET_EMSGSIZE;
+ case EBADF:
+ return error_new(E_NET_ECLOSED);
+ case EMSGSIZE:
+ return error_new(E_POSIX_EMSGSIZE);
default:
- return -NET_EOTHER;
+ return errno2lm(errnum);
}
}
@@ -136,15 +139,15 @@ void hostnet_tcp_listener_init(struct hostnet_tcp_listener *self, uint16_t port)
addr.in.sin_port = htons(port);
listenerfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenerfd < 0)
- error(1, errno, "socket");
+ __error(1, errno, "socket");
if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
- error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd);
+ __error(1, errno, "setsockopt(fd=%d, SO_REUSEADDR=1)", listenerfd);
if (setsockopt(listenerfd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)) < 0)
- error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd);
+ __error(1, errno, "setsockopt(fd=%d, SO_REUSEPORT=1)", listenerfd);
if (bind(listenerfd, &addr.gen, sizeof addr) < 0)
- error(1, errno, "bind(fd=%d)", listenerfd);
+ __error(1, errno, "bind(fd=%d)", listenerfd);
if (listen(listenerfd, 0) < 0)
- error(1, errno, "listen(fd=%d)", listenerfd);
+ __error(1, errno, "listen(fd=%d)", listenerfd);
self->fd = listenerfd;
}
@@ -158,44 +161,48 @@ struct hostnet_pthread_accept_args {
int listenerfd;
int *ret_connfd;
+ host_errno_t *ret_errno;
};
static void *hostnet_pthread_accept(void *_args) {
struct hostnet_pthread_accept_args *args = _args;
*(args->ret_connfd) = accept(args->listenerfd, NULL, NULL);
- if (*(args->ret_connfd) < 0)
- *(args->ret_connfd) = -errno;
+ *(args->ret_errno) = errno;
WAKE_COROUTINE(args);
return NULL;
}
-static lo_interface net_stream_conn hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) {
+static net_stream_conn_or_error hostnet_tcplist_accept(struct hostnet_tcp_listener *listener) {
assert(listener);
int ret_connfd;
+ host_errno_t ret_errno;
struct hostnet_pthread_accept_args args = {
.cr_thread = pthread_self(),
.cr_coroutine = cr_getcid(),
.listenerfd = listener->fd,
.ret_connfd = &ret_connfd,
+ .ret_errno = &ret_errno,
};
- if (RUN_PTHREAD(hostnet_pthread_accept, &args))
- return LO_NULL(net_stream_conn);
-
+ host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_accept, &args);
+ if (thread_errno)
+ return ERROR_NEW_ERR(net_stream_conn, errno2lm(thread_errno));
if (ret_connfd < 0)
- return LO_NULL(net_stream_conn);
+ return ERROR_NEW_ERR(net_stream_conn, hostnet_error(ret_errno, OP_RECV));
listener->active_conn.fd = ret_connfd;
listener->active_conn.read_deadline_ns = 0;
- return lo_box_hostnet_tcp_as_net_stream_conn(&listener->active_conn);
+ return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, &listener->active_conn));
}
/* TCP listener close() *******************************************************/
-static int hostnet_tcplist_close(struct hostnet_tcp_listener *listener) {
+static error hostnet_tcplist_close(struct hostnet_tcp_listener *listener) {
assert(listener);
- return hostnet_map_negerrno(shutdown(listener->fd, SHUT_RDWR) ? -errno : 0, OP_NONE);
+ if (shutdown(listener->fd, SHUT_RDWR))
+ return hostnet_error(errno, OP_CLOSE);
+ return ERROR_NULL;
}
/* TCP read() *****************************************************************/
@@ -215,29 +222,36 @@ struct hostnet_pthread_readv_args {
const struct iovec *iov;
int iovcnt;
- ssize_t *ret;
+ size_t *ret_size;
+ host_errno_t *ret_errno;
};
static void *hostnet_pthread_readv(void *_args) {
struct hostnet_pthread_readv_args *args = _args;
- *(args->ret) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
- &args->timeout, sizeof(args->timeout));
- if (*(args->ret) < 0)
+ int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
+ &args->timeout, sizeof(args->timeout));
+ if (r_i) {
+ *args->ret_size = 0;
+ *args->ret_errno = errno;
goto end;
+ }
- *(args->ret) = readv(args->connfd, args->iov, args->iovcnt);
- if (*(args->ret) < 0)
+ ssize_t r_ss = readv(args->connfd, args->iov, args->iovcnt);
+ if (r_ss < 0) {
+ *args->ret_size = 0;
+ *args->ret_errno = errno;
goto end;
+ }
+ *args->ret_size = r_ss;
+ *args->ret_errno = 0;
end:
- if (*(args->ret) < 0)
- *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND);
WAKE_COROUTINE(args);
return NULL;
}
-static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) {
+static size_t_or_error hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) {
assert(conn);
assert(iov);
assert(iovcnt > 0);
@@ -246,7 +260,8 @@ static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct io
count += iov[i].iov_len;
assert(count);
- ssize_t ret;
+ size_t ret_size;
+ host_errno_t ret_errno;
struct hostnet_pthread_readv_args args = {
.cr_thread = pthread_self(),
.cr_coroutine = cr_getcid(),
@@ -255,20 +270,26 @@ static ssize_t hostnet_tcp_readv(struct _hostnet_tcp_conn *conn, const struct io
.iov = iov,
.iovcnt = iovcnt,
- .ret = &ret,
+ .ret_size = &ret_size,
+ .ret_errno = &ret_errno,
};
if (conn->read_deadline_ns) {
uint64_t now_ns = LO_CALL(bootclock, get_time_ns);
if (conn->read_deadline_ns < now_ns)
- return -NET_ERECV_TIMEOUT;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT));
args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns);
} else {
args.timeout = (host_us_time_t){};
}
- if (RUN_PTHREAD(hostnet_pthread_readv, &args))
- return -NET_ETHREAD;
- return ret;
+ host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_readv, &args);
+ if (thread_errno)
+ return ERROR_NEW_ERR(size_t, errno2lm(thread_errno));
+ if (ret_errno)
+ return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV));
+ if (!ret_size)
+ return ERROR_NEW_ERR(size_t, error_new(E_EOF));
+ return ERROR_NEW_VAL(size_t, ret_size);
}
/* TCP write() ****************************************************************/
@@ -281,7 +302,8 @@ struct hostnet_pthread_writev_args {
const struct iovec *iov;
int iovcnt;
- ssize_t *ret;
+ size_t *ret_size;
+ host_errno_t *ret_errno;
};
static void *hostnet_pthread_writev(void *_args) {
@@ -299,7 +321,7 @@ static void *hostnet_pthread_writev(void *_args) {
while (done < count) {
ssize_t r = writev(args->connfd, iov, iovcnt);
if (r < 0) {
- hostnet_map_negerrno(-errno, OP_RECV);
+ *args->ret_errno = errno;
break;
}
done += r;
@@ -314,12 +336,13 @@ static void *hostnet_pthread_writev(void *_args) {
}
}
if (done == count)
- *(args->ret) = done;
+ *args->ret_errno = 0;
+ *args->ret_size = done;
WAKE_COROUTINE(args);
return NULL;
}
-static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) {
+static size_t_and_error hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct iovec *iov, int iovcnt) {
assert(conn);
assert(iov);
assert(iovcnt > 0);
@@ -328,7 +351,8 @@ static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct i
count += iov[i].iov_len;
assert(count);
- ssize_t ret;
+ size_t ret_size;
+ host_errno_t ret_errno;
struct hostnet_pthread_writev_args args = {
.cr_thread = pthread_self(),
.cr_coroutine = cr_getcid(),
@@ -337,26 +361,34 @@ static ssize_t hostnet_tcp_writev(struct _hostnet_tcp_conn *conn, const struct i
.iov = iov,
.iovcnt = iovcnt,
- .ret = &ret,
+ .ret_size = &ret_size,
+ .ret_errno = &ret_errno,
};
- if (RUN_PTHREAD(hostnet_pthread_writev, &args))
- return -NET_ETHREAD;
- return ret;
+ int thread_errno = RUN_PTHREAD(hostnet_pthread_writev, &args);
+ if (thread_errno)
+ return ERROR_AND(size_t, 0, errno2lm(thread_errno));
+ return ERROR_AND(size_t, ret_size, ret_errno ? hostnet_error(ret_errno, OP_SEND) : ERROR_NULL);
}
/* TCP close() ****************************************************************/
-static int hostnet_tcp_close(struct _hostnet_tcp_conn *conn) {
+static error hostnet_tcp_close(struct _hostnet_tcp_conn *conn) {
assert(conn);
- return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RDWR) ? -errno : 0, OP_NONE);
+ if (shutdown(conn->fd, SHUT_RDWR))
+ return hostnet_error(errno, OP_CLOSE);
+ return ERROR_NULL;
}
-static int hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) {
+static error hostnet_tcp_close_read(struct _hostnet_tcp_conn *conn) {
assert(conn);
- return hostnet_map_negerrno(shutdown(conn->fd, SHUT_RD) ? -errno : 0, OP_NONE);
+ if (shutdown(conn->fd, SHUT_RD))
+ return hostnet_error(errno, OP_CLOSE);
+ return ERROR_NULL;
}
-static int hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) {
+static error hostnet_tcp_close_write(struct _hostnet_tcp_conn *conn) {
assert(conn);
- return hostnet_map_negerrno(shutdown(conn->fd, SHUT_WR) ? -errno : 0, OP_NONE);
+ if (shutdown(conn->fd, SHUT_WR))
+ return hostnet_error(errno, OP_CLOSE);
+ return ERROR_NULL;
}
/* UDP init() *****************************************************************/
@@ -375,11 +407,11 @@ void hostnet_udp_conn_init(struct hostnet_udp_conn *self, uint16_t port) {
addr.in.sin_port = htons(port);
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
- error(1, errno, "socket");
+ __error(1, errno, "socket");
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &(int){1}, sizeof(int)) < 0)
- error(1, errno, "setsockopt(fd=%d, SO_BROADCAST=1)", fd);
+ __error(1, errno, "setsockopt(fd=%d, SO_BROADCAST=1)", fd);
if (bind(fd, &addr.gen, sizeof addr) < 0)
- error(1, errno, "bind");
+ __error(1, errno, "bind");
self->fd = fd;
self->read_deadline_ns = 0;
@@ -397,7 +429,8 @@ struct hostnet_pthread_sendto_args {
struct net_ip4_addr node;
uint16_t port;
- ssize_t *ret;
+ size_t *ret_size;
+ host_errno_t *ret_errno;
};
static void *hostnet_pthread_sendto(void *_args) {
@@ -415,18 +448,24 @@ static void *hostnet_pthread_sendto(void *_args) {
(((uint32_t)args->node.octets[1])<< 8) |
(((uint32_t)args->node.octets[0])<< 0) ;
addr.in.sin_port = htons(args->port);
- *(args->ret) = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr));
- if (*(args->ret) < 0)
- *(args->ret) = hostnet_map_negerrno(-errno, OP_SEND);
+ ssize_t r = sendto(args->connfd, args->buf, args->count, 0, &addr.gen, sizeof(addr));
+ if (r < 0) {
+ *args->ret_size = 0;
+ *args->ret_errno = errno;
+ } else {
+ *args->ret_size = r;
+ *args->ret_errno = 0;
+ }
WAKE_COROUTINE(args);
return NULL;
}
-static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count,
- struct net_ip4_addr node, uint16_t port) {
+static error hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size_t count,
+ struct net_ip4_addr node, uint16_t port) {
assert(conn);
- ssize_t ret;
+ size_t ret_size;
+ host_errno_t ret_errno;
struct hostnet_pthread_sendto_args args = {
.cr_thread = pthread_self(),
.cr_coroutine = cr_getcid(),
@@ -437,11 +476,15 @@ static ssize_t hostnet_udp_sendto(struct hostnet_udp_conn *conn, void *buf, size
.node = node,
.port = port,
- .ret = &ret,
+ .ret_size = &ret_size,
+ .ret_errno = &ret_errno,
};
- if (RUN_PTHREAD(hostnet_pthread_sendto, &args))
- return -NET_ETHREAD;
- return ret;
+ int thread_errno = RUN_PTHREAD(hostnet_pthread_sendto, &args);
+ if (thread_errno)
+ return errno2lm(thread_errno);
+ if (ret_errno)
+ return hostnet_error(ret_errno, OP_SEND);
+ return ERROR_NULL;
}
/* UDP recvfrom() *************************************************************/
@@ -462,7 +505,8 @@ struct hostnet_pthread_recvfrom_args {
void *buf;
size_t count;
- ssize_t *ret_size;
+ size_t *ret_size;
+ host_errno_t *ret_errno;
struct net_ip4_addr *ret_node;
uint16_t *ret_port;
};
@@ -477,15 +521,23 @@ static void *hostnet_pthread_recvfrom(void *_args) {
} addr = {};
socklen_t addr_size = sizeof(addr);
- *(args->ret_size) = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
- &args->timeout, sizeof(args->timeout));
- if (*(args->ret_size) < 0)
+ int r_i = setsockopt(args->connfd, SOL_SOCKET, SO_RCVTIMEO,
+ &args->timeout, sizeof(args->timeout));
+ if (r_i) {
+ *args->ret_size = 0;
+ *args->ret_errno = errno;
goto end;
+ }
- *(args->ret_size) = recvfrom(args->connfd, args->buf, args->count,
- MSG_TRUNC, &addr.gen, &addr_size);
- if (*(args->ret_size) < 0)
+ ssize_t r_ss = recvfrom(args->connfd, args->buf, args->count,
+ MSG_TRUNC, &addr.gen, &addr_size);
+ if (r_ss < 0) {
+ *args->ret_size = 0;
+ *args->ret_errno = errno;
goto end;
+ }
+ *args->ret_size = r_ss;
+ *args->ret_errno = 0;
assert(addr.in.sin_family == AF_INET);
if (args->ret_node) {
@@ -499,17 +551,16 @@ static void *hostnet_pthread_recvfrom(void *_args) {
}
end:
- if (*(args->ret_size) < 0)
- *(args->ret_size) = hostnet_map_negerrno(-errno, OP_RECV);
WAKE_COROUTINE(args);
return NULL;
}
-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) {
+static size_t_or_error hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, size_t count,
+ struct net_ip4_addr *ret_node, uint16_t *ret_port) {
assert(conn);
- ssize_t ret;
+ size_t ret_size;
+ host_errno_t ret_errno;
struct hostnet_pthread_recvfrom_args args = {
.cr_thread = pthread_self(),
.cr_coroutine = cr_getcid(),
@@ -518,28 +569,34 @@ static ssize_t hostnet_udp_recvfrom(struct hostnet_udp_conn *conn, void *buf, si
.buf = buf,
.count = count,
- .ret_size = &ret,
+ .ret_size = &ret_size,
+ .ret_errno = &ret_errno,
.ret_node = ret_node,
.ret_port = ret_port,
};
if (conn->read_deadline_ns) {
uint64_t now_ns = LO_CALL(bootclock, get_time_ns);
if (conn->read_deadline_ns < now_ns)
- return -NET_ERECV_TIMEOUT;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT));
args.timeout = ns_to_host_us_time(conn->read_deadline_ns-now_ns);
} else {
args.timeout = (host_us_time_t){};
}
- if (RUN_PTHREAD(hostnet_pthread_recvfrom, &args))
- return -NET_ETHREAD;
- return ret;
+ host_errno_t thread_errno = RUN_PTHREAD(hostnet_pthread_recvfrom, &args);
+ if (thread_errno)
+ return ERROR_NEW_ERR(size_t, errno2lm(thread_errno));
+ if (ret_errno)
+ return ERROR_NEW_ERR(size_t, hostnet_error(ret_errno, OP_RECV));
+ return ERROR_NEW_VAL(size_t, ret_size);
}
/* UDP close() ****************************************************************/
-static int hostnet_udp_close(struct hostnet_udp_conn *conn) {
+static error hostnet_udp_close(struct hostnet_udp_conn *conn) {
assert(conn);
- return hostnet_map_negerrno(close(conn->fd) ? -errno : 0, OP_NONE);
+ if (close(conn->fd))
+ return hostnet_error(errno, OP_CLOSE);
+ return ERROR_NULL;
}
diff --git a/libhw_cr/host_util.c b/libhw_cr/host_util.c
index 8cacd57..2d45490 100644
--- a/libhw_cr/host_util.c
+++ b/libhw_cr/host_util.c
@@ -4,9 +4,13 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
-#include <error.h> /* for error(3gnu) */
+#include <errno.h> /* for E* */
#include <signal.h> /* for SIGRTMIN, SIGRTMAX */
+#define error __error
+#include <error.h>
+#undef error
+
#include <libhw/generic/alarmclock.h> /* for {X}S_PER_S */
#include "host_util.h"
@@ -18,7 +22,7 @@ int host_sigrt_alloc(void) {
next = SIGRTMIN;
int ret = next++;
if (ret > SIGRTMAX)
- error(1, 0, "SIGRTMAX exceeded");
+ __error(1, 0, "SIGRTMAX exceeded");
return ret;
}
@@ -48,3 +52,94 @@ uint64_t ns_from_host_ns_time(host_ns_time_t host_time) {
return (((uint64_t)host_time.tv_sec) * NS_PER_S) +
((uint64_t)host_time.tv_nsec);
}
+
+_errnum errno_host2lm(host_errno_t host) {
+ switch (host) {
+ case E2BIG: return E_POSIX_E2BIG;
+ case EACCES: return E_POSIX_EACCES;
+ case EADDRINUSE: return E_POSIX_EADDRINUSE;
+ case EADDRNOTAVAIL: return E_POSIX_EADDRNOTAVAIL;
+ case EAFNOSUPPORT: return E_POSIX_EAFNOSUPPORT;
+ case EAGAIN: return E_POSIX_EAGAIN;
+ case EALREADY: return E_POSIX_EALREADY;
+ case EBADF: return E_POSIX_EBADF;
+ case EBADMSG: return E_POSIX_EBADMSG;
+ case EBUSY: return E_POSIX_EBUSY;
+ case ECANCELED: return E_POSIX_ECANCELED;
+ case ECHILD: return E_POSIX_ECHILD;
+ case ECONNABORTED: return E_POSIX_ECONNABORTED;
+ case ECONNREFUSED: return E_POSIX_ECONNREFUSED;
+ case ECONNRESET: return E_POSIX_ECONNRESET;
+ case EDEADLK: return E_POSIX_EDEADLK;
+ case EDESTADDRREQ: return E_POSIX_EDESTADDRREQ;
+ case EDOM: return E_POSIX_EDOM;
+ case EDQUOT: return E_POSIX_EDQUOT;
+ case EEXIST: return E_POSIX_EEXIST;
+ case EFAULT: return E_POSIX_EFAULT;
+ case EFBIG: return E_POSIX_EFBIG;
+ case EHOSTUNREACH: return E_POSIX_EHOSTUNREACH;
+ case EIDRM: return E_POSIX_EIDRM;
+ case EILSEQ: return E_POSIX_EILSEQ;
+ case EINPROGRESS: return E_POSIX_EINPROGRESS;
+ case EINTR: return E_POSIX_EINTR;
+ case EINVAL: return E_POSIX_EINVAL;
+ case EIO: return E_POSIX_EIO;
+ case EISCONN: return E_POSIX_EISCONN;
+ case EISDIR: return E_POSIX_EISDIR;
+ case ELOOP: return E_POSIX_ELOOP;
+ case EMFILE: return E_POSIX_EMFILE;
+ case EMLINK: return E_POSIX_EMLINK;
+ case EMSGSIZE: return E_POSIX_EMSGSIZE;
+ case EMULTIHOP: return E_POSIX_EMULTIHOP;
+ case ENAMETOOLONG: return E_POSIX_ENAMETOOLONG;
+ case ENETDOWN: return E_POSIX_ENETDOWN;
+ case ENETRESET: return E_POSIX_ENETRESET;
+ case ENETUNREACH: return E_POSIX_ENETUNREACH;
+ case ENFILE: return E_POSIX_ENFILE;
+ case ENOBUFS: return E_POSIX_ENOBUFS;
+ case ENODEV: return E_POSIX_ENODEV;
+ case ENOENT: return E_POSIX_ENOENT;
+ case ENOEXEC: return E_POSIX_ENOEXEC;
+ case ENOLCK: return E_POSIX_ENOLCK;
+ case ENOLINK: return E_POSIX_ENOLINK;
+ case ENOMEM: return E_POSIX_ENOMEM;
+ case ENOMSG: return E_POSIX_ENOMSG;
+ case ENOPROTOOPT: return E_POSIX_ENOPROTOOPT;
+ case ENOSPC: return E_POSIX_ENOSPC;
+ case ENOSYS: return E_POSIX_ENOSYS;
+ case ENOTCONN: return E_POSIX_ENOTCONN;
+ case ENOTDIR: return E_POSIX_ENOTDIR;
+ case ENOTEMPTY: return E_POSIX_ENOTEMPTY;
+ case ENOTRECOVERABLE: return E_POSIX_ENOTRECOVERABLE;
+ case ENOTSOCK: return E_POSIX_ENOTSOCK;
+ case ENOTSUP: return E_POSIX_ENOTSUP;
+ case ENOTTY: return E_POSIX_ENOTTY;
+ case ENXIO: return E_POSIX_ENXIO;
+ case EOVERFLOW: return E_POSIX_EOVERFLOW;
+ case EOWNERDEAD: return E_POSIX_EOWNERDEAD;
+ case EPERM: return E_POSIX_EPERM;
+ case EPIPE: return E_POSIX_EPIPE;
+ case EPROTO: return E_POSIX_EPROTO;
+ case EPROTONOSUPPORT: return E_POSIX_EPROTONOSUPPORT;
+ case EPROTOTYPE: return E_POSIX_EPROTOTYPE;
+ case ERANGE: return E_POSIX_ERANGE;
+ case EROFS: return E_POSIX_EROFS;
+ case ESOCKTNOSUPPORT: return E_POSIX_ESOCKTNOSUPPORT;
+ case ESPIPE: return E_POSIX_ESPIPE;
+ case ESRCH: return E_POSIX_ESRCH;
+ case ESTALE: return E_POSIX_ESTALE;
+ case ETIMEDOUT: return E_POSIX_ETIMEDOUT;
+ case ETXTBSY: return E_POSIX_ETXTBSY;
+ case EXDEV: return E_POSIX_EXDEV;
+ default:
+ switch (host) {
+ case EOPNOTSUPP: return E_POSIX_EOPNOTSUPP;
+ case EWOULDBLOCK: return E_POSIX_EWOULDBLOCK;
+ default: return E_EUNKNOWN;
+ }
+ }
+}
+
+error errno2lm(host_errno_t host) {
+ return error_new(errno_host2lm(host));
+}
diff --git a/libhw_cr/host_util.h b/libhw_cr/host_util.h
index 4adb94e..7e559ef 100644
--- a/libhw_cr/host_util.h
+++ b/libhw_cr/host_util.h
@@ -11,6 +11,8 @@
#include <sys/time.h> /* for struct timeval */
#include <time.h> /* for struct timespec */
+#include <libmisc/error.h> /* for _errnum, error */
+
int host_sigrt_alloc(void);
typedef struct timeval host_us_time_t;
@@ -21,4 +23,8 @@ host_ns_time_t ns_to_host_ns_time(uint64_t time_ns);
uint64_t ns_from_host_us_time(host_us_time_t host_time);
uint64_t ns_from_host_ns_time(host_ns_time_t host_time);
+#define host_errno_t int
+_errnum errno_host2lm(host_errno_t host);
+error errno2lm(host_errno_t host);
+
#endif /* _LIBHW_CR_HOST_UTIL_H_ */
diff --git a/libhw_cr/rp2040_hwspi.c b/libhw_cr/rp2040_hwspi.c
index a7840e8..d717a79 100644
--- a/libhw_cr/rp2040_hwspi.c
+++ b/libhw_cr/rp2040_hwspi.c
@@ -136,7 +136,7 @@ void _rp2040_hwspi_init(struct rp2040_hwspi *self,
dmairq_set_and_enable_exclusive_handler(DMAIRQ_0, self->dma_rx_data, rp2040_hwspi_intrhandler, self);
}
-static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct duplex_iovec *iov, int iovcnt) {
+static size_t_and_error rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct duplex_iovec *iov, int iovcnt) {
assert(self);
assert(self->inst);
assert(iov);
@@ -268,4 +268,5 @@ static void rp2040_hwspi_readwritev(struct rp2040_hwspi *self, const struct dupl
cr_restore_interrupts(saved);
cr_sema_wait(&self->sema);
self->dead_until_ns = LO_CALL(bootclock, get_time_ns) + self->min_delay_ns;
+ return ERROR_AND(size_t, count, ERROR_NULL);
}
diff --git a/libhw_cr/rp2040_hwtimer.c b/libhw_cr/rp2040_hwtimer.c
index 8227abb..d9f0a24 100644
--- a/libhw_cr/rp2040_hwtimer.c
+++ b/libhw_cr/rp2040_hwtimer.c
@@ -44,7 +44,7 @@ static_assert(sizeof(hwtimers)/sizeof(hwtimers[0]) == _RP2040_HWALARM_NUM);
lo_interface alarmclock rp2040_hwtimer(enum rp2040_hwalarm_instance alarm_num) {
assert(alarm_num < _RP2040_HWALARM_NUM);
- return lo_box_rp2040_hwtimer_as_alarmclock(&hwtimers[alarm_num]);
+ return LO_BOX(alarmclock, &hwtimers[alarm_num]);
}
diff --git a/libhw_cr/w5500.c b/libhw_cr/w5500.c
index c318819..594b391 100644
--- a/libhw_cr/w5500.c
+++ b/libhw_cr/w5500.c
@@ -459,11 +459,11 @@ static lo_interface net_stream_listener w5500_if_tcp_listen(struct w5500 *chip,
sock->read_deadline_ns = 0;
sock->list_open = true;
- return lo_box_w5500_tcplist_as_net_stream_listener(sock);
+ return LO_BOX(net_stream_listener, sock);
}
-static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip,
- struct net_ip4_addr node, uint16_t port) {
+static net_stream_conn_or_error 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));
@@ -472,7 +472,7 @@ static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip,
struct _w5500_socket *socket = w5500_alloc_socket(chip);
if (!socket) {
log_debugln("tcp_dial() => no sock");
- return LO_NULL(net_stream_conn);
+ return ERROR_NEW_ERR(net_stream_conn, error_new(E_POSIX_ENOTSOCK));
}
uint8_t socknum = socket->socknum;
log_debugln("tcp_dial() => sock[", socknum, "]");
@@ -509,7 +509,7 @@ static lo_interface net_stream_conn w5500_if_tcp_dial(struct w5500 *chip,
cr_yield();
break;
case STATE_TCP_ESTABLISHED:
- return lo_box_w5500_tcp_as_net_stream_conn(socket);
+ return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, socket));
default:
goto restart;
}
@@ -545,7 +545,7 @@ static lo_interface net_packet_conn w5500_if_udp_conn(struct w5500 *chip, uint16
cr_yield();
cr_mutex_unlock(&chip->mu);
- return lo_box_w5500_udp_as_net_packet_conn(socket);
+ return LO_BOX(net_packet_conn, socket);
}
static bool w5500_if_arp_ping(struct w5500 *chip, struct net_ip4_addr addr) {
@@ -559,20 +559,20 @@ static bool w5500_if_arp_ping(struct w5500 *chip, struct net_ip4_addr addr) {
sock = &chip->sockets[i];
}
assert(sock);
- ssize_t v = w5500_udp_sendto(sock, "BOGUS_PACKET_TO_TRIGGER_AN_ARP", 17, addr, 5000);
- log_debugln("arp_ping => ", v);
- return v != -NET_EARP_TIMEOUT;
+ error err = w5500_udp_sendto(sock, "BOGUS_PACKET_TO_TRIGGER_AN_ARP", 17, addr, 5000);
+ log_debugln("arp_ping => ", (error, err));
+ return err.num != E_NET_EARP_TIMEOUT;
}
/* tcp_listener methods *******************************************************/
-static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *socket) {
+static net_stream_conn_or_error w5500_tcplist_accept(struct _w5500_socket *socket) {
ASSERT_SELF(stream_listener, TCP);
restart:
if (!socket->list_open) {
log_debugln("tcp_listener.accept() => already closed");
- return LO_NULL(net_stream_conn);
+ return ERROR_NEW_ERR(net_stream_conn, error_new(E_NET_ECLOSED));
}
cr_mutex_lock(&chip->mu);
@@ -598,28 +598,28 @@ static lo_interface net_stream_conn w5500_tcplist_accept(struct _w5500_socket *s
break;
case STATE_TCP_ESTABLISHED:
socket->read_open = true;
- /* fall-through */
+ [[fallthrough]];
case STATE_TCP_CLOSE_WAIT:
socket->write_open = true;
- return lo_box_w5500_tcp_as_net_stream_conn(socket);
+ return ERROR_NEW_VAL(net_stream_conn, LO_BOX(net_stream_conn, socket));
default:
goto restart;
}
}
}
-static int w5500_tcplist_close(struct _w5500_socket *socket) {
+static error w5500_tcplist_close(struct _w5500_socket *socket) {
log_debugln("tcp_listener.close()");
ASSERT_SELF(stream_listener, TCP);
socket->list_open = false;
w5500_tcp_maybe_free(chip, socket);
- return 0;
+ return ERROR_NULL;
}
/* tcp_conn methods ***********************************************************/
-static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
+static size_t_and_error w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
assert(iov);
assert(iovcnt > 0);
size_t count = 0;
@@ -653,14 +653,14 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
while (done < count) {
if (!socket->write_open) {
log_debugln(" => soft closed");
- return -NET_ECLOSED;
+ return ERROR_AND(size_t, done, error_new(E_NET_ECLOSED));
}
cr_mutex_lock(&chip->mu);
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
if (state != STATE_TCP_ESTABLISHED && state != STATE_TCP_CLOSE_WAIT) {
cr_mutex_unlock(&chip->mu);
log_debugln(" => hard closed");
- return -NET_ECLOSED;
+ return ERROR_AND(size_t, done, error_new(E_NET_ECLOSED));
}
uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
@@ -689,7 +689,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
break;
case SOCKINTR_SEND_TIMEOUT:
log_debugln(" => ACK timeout");
- return -NET_EACK_TIMEOUT;
+ return ERROR_AND(size_t, done, error_new(E_NET_EACK_TIMEOUT));
case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
assert_notreached("send both OK and timed out?");
default:
@@ -697,7 +697,7 @@ static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec
}
}
log_debugln(" => send finished");
- return done;
+ return ERROR_AND(size_t, done, ERROR_NULL);
}
static void w5500_tcp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) {
@@ -711,7 +711,7 @@ static void w5500_tcp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
+static size_t_or_error w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) {
assert(iov);
assert(iovcnt > 0);
size_t count = 0;
@@ -734,12 +734,12 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec
if (!socket->read_open) {
LO_CALL(bootclock, del_trigger, &trigger);
log_debugln(" => soft closed");
- return -NET_ECLOSED;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED));
}
if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) {
LO_CALL(bootclock, del_trigger, &trigger);
log_debugln(" => recv timeout");
- return -NET_ERECV_TIMEOUT;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT));
}
cr_mutex_lock(&chip->mu);
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
@@ -752,7 +752,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec
LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
log_debugln(" => hard closed");
- return -NET_ECLOSED;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED));
}
avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
@@ -763,7 +763,7 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec
LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
log_debugln(" => EOF");
- return 0;
+ return ERROR_NEW_ERR(size_t, error_new(E_EOF));
}
cr_mutex_unlock(&chip->mu);
@@ -782,10 +782,10 @@ static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec
/* Return. */
LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
- return avail;
+ return ERROR_NEW_VAL(size_t, avail);
}
-static int w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) {
+static error w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr) {
log_debugln("tcp_conn.close(rd=", rd, ", wr=", wr, ")");
ASSERT_SELF(stream_conn, TCP);
@@ -813,17 +813,17 @@ static int w5500_tcp_close_inner(struct _w5500_socket *socket, bool rd, bool wr)
}
w5500_tcp_maybe_free(chip, socket);
- return 0;
+ return ERROR_NULL;
}
-static int w5500_tcp_close(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, true); }
-static int w5500_tcp_close_read(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, false); }
-static int w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, false, true); }
+static error w5500_tcp_close(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, true); }
+static error w5500_tcp_close_read(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, true, false); }
+static error w5500_tcp_close_write(struct _w5500_socket *socket) { return w5500_tcp_close_inner(socket, false, true); }
/* udp_conn methods ***********************************************************/
-static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
- struct net_ip4_addr node, uint16_t port) {
+static error w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count,
+ struct net_ip4_addr node, uint16_t port) {
log_debugln("udp_conn.sendto()");
ASSERT_SELF(packet_conn, UDP);
assert(buf);
@@ -832,7 +832,7 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t
uint16_t bufsize = ((uint16_t)w5500ll_read_sock_reg(chip->spidev, socknum, tx_buf_size))*1024;
if (count > bufsize) {
log_debugln(" => msg too large");
- return -NET_EMSGSIZE;
+ return error_new(E_POSIX_EMSGSIZE);
}
for (;;) {
@@ -841,7 +841,7 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t
if (state != STATE_UDP) {
cr_mutex_unlock(&chip->mu);
log_debugln(" => closed");
- return -NET_ECLOSED;
+ return error_new(E_NET_ECLOSED);
}
uint16_t freesize = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_free_size));
@@ -871,10 +871,10 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t
switch (cr_chan_recv(&socket->write_ch)) {
case SOCKINTR_SEND_OK:
log_debugln(" => sent");
- return count;
+ return ERROR_NULL;
case SOCKINTR_SEND_TIMEOUT:
log_debugln(" => ARP timeout");
- return -NET_EARP_TIMEOUT;
+ return error_new(E_NET_EARP_TIMEOUT);
case SOCKINTR_SEND_OK|SOCKINTR_SEND_TIMEOUT:
assert_notreached("send both OK and timed out?");
default:
@@ -893,8 +893,8 @@ static void w5500_udp_alarm_handler(void *_arg) {
cr_sema_signal_from_intrhandler(&socket->read_sema);
}
-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) {
+static size_t_or_error w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_t count,
+ struct net_ip4_addr *ret_node, uint16_t *ret_port) {
log_debugln("udp_conn.recvfrom()");
ASSERT_SELF(packet_conn, UDP);
assert(buf);
@@ -913,14 +913,14 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_
if (socket->read_deadline_ns && socket->read_deadline_ns <= LO_CALL(bootclock, get_time_ns)) {
LO_CALL(bootclock, del_trigger, &trigger);
log_debugln(" => recv timeout");
- return -NET_ERECV_TIMEOUT;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ERECV_TIMEOUT));
}
cr_mutex_lock(&chip->mu);
uint8_t state = w5500ll_read_sock_reg(chip->spidev, socknum, state);
if (state != STATE_UDP) {
LO_CALL(bootclock, del_trigger, &trigger);
log_debugln(" => hard closed");
- return -NET_ECLOSED;
+ return ERROR_NEW_ERR(size_t, error_new(E_NET_ECLOSED));
}
avail = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, rx_size));
@@ -964,14 +964,14 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_
/* Return. */
LO_CALL(bootclock, del_trigger, &trigger);
cr_mutex_unlock(&chip->mu);
- return len;
+ return ERROR_NEW_VAL(size_t, len);
}
-static int w5500_udp_close(struct _w5500_socket *socket) {
+static error w5500_udp_close(struct _w5500_socket *socket) {
log_debugln("udp_conn.close()");
ASSERT_SELF(packet_conn, UDP);
w5500_socket_close(socket);
w5500_free_socket(chip, socket);
- return 0;
+ return ERROR_NULL;
}