diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-02 13:30:05 -0700 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2025-03-02 13:30:05 -0700 |
commit | 255baf6db201dcdf8da017d55c577622f217a888 (patch) | |
tree | 905a389bc9fdf072cbdf7e9f21b2b936881eb620 /libhw/w5500.c | |
parent | 188ac62a0c0f5519f5d45519fa7d224cb25305c6 (diff) | |
parent | 5a84ba2361cecade0343b88f696b6a63454cc3c6 (diff) |
Merge branch 'lukeshu/iov'
Diffstat (limited to 'libhw/w5500.c')
-rw-r--r-- | libhw/w5500.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/libhw/w5500.c b/libhw/w5500.c index a8777db..64b373b 100644 --- a/libhw/w5500.c +++ b/libhw/w5500.c @@ -125,9 +125,19 @@ static const char *w5500_state_str(uint8_t state) { /* libobj *********************************************************************/ +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcplist, static) LO_IMPLEMENTATION_C(net_stream_listener, struct _w5500_socket, w5500_tcplist, static) + +LO_IMPLEMENTATION_C(io_reader, struct _w5500_socket, w5500_tcp, static) +LO_IMPLEMENTATION_C(io_writer, struct _w5500_socket, w5500_tcp, static) +LO_IMPLEMENTATION_C(io_readwriter, struct _w5500_socket, w5500_tcp, static) +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_tcp, static) +LO_IMPLEMENTATION_C(io_bidi_closer, struct _w5500_socket, w5500_tcp, static) LO_IMPLEMENTATION_C(net_stream_conn, struct _w5500_socket, w5500_tcp, static) + +LO_IMPLEMENTATION_C(io_closer, struct _w5500_socket, w5500_udp, 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 ********************************************************/ @@ -586,10 +596,14 @@ static int w5500_tcplist_close(struct _w5500_socket *socket) { /* tcp_conn methods ***********************************************************/ -static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t count) { +static ssize_t w5500_tcp_writev(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { + assert(iov); + assert(iovcnt > 0); + size_t count = 0; + for (int i = 0; i < iovcnt; i++) + count += iov[i].iov_len; debugf("tcp_conn.write(%zu)", count); ASSERT_SELF(stream_conn, TCP); - assert(count == 0 || buf); if (count == 0) return 0; @@ -639,7 +653,7 @@ static ssize_t w5500_tcp_write(struct _w5500_socket *socket, void *buf, size_t c if ((size_t)freesize > count-done) freesize = count-done; uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_write_pointer)); - w5500ll_write(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), &((char *)buf)[done], freesize); + w5500ll_writev(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), iov, iovcnt, done, freesize); w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+freesize)); /* Submit the queue. */ @@ -675,10 +689,14 @@ static void w5500_tcp_alarm_handler(void *_arg) { cr_sema_signal_from_intrhandler(&socket->read_sema); } -static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t count) { - debugf("tcp_conn.read()"); +static ssize_t w5500_tcp_readv(struct _w5500_socket *socket, const struct iovec *iov, int iovcnt) { + assert(iov); + assert(iovcnt > 0); + size_t count = 0; + for (int i = 0; i < iovcnt; i++) + count += iov[i].iov_len; + debugf("tcp_conn.read(%zu)", count); ASSERT_SELF(stream_conn, TCP); - assert(count == 0 || buf); if (count == 0) return 0; @@ -736,7 +754,7 @@ static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t co /* Read the data. */ if ((size_t)avail > count) avail = count; - w5500ll_read(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), buf, avail); + w5500ll_readv(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), iov, iovcnt, avail); /* Tell the chip that we read the data. */ w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+avail)); w5500_socket_cmd(socket, CMD_RECV); @@ -746,7 +764,7 @@ static ssize_t w5500_tcp_read(struct _w5500_socket *socket, void *buf, size_t co return avail; } -static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) { +static int w5500_tcp_close_inner(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); @@ -777,6 +795,10 @@ static int w5500_tcp_close(struct _w5500_socket *socket, bool rd, bool wr) { return 0; } +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); } + /* udp_conn methods ***********************************************************/ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t count, @@ -816,7 +838,10 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t w5500ll_write_sock_reg(chip->spidev, socknum, remote_port, uint16be_marshal(port)); /* Queue data to be sent. */ uint16_t ptr = uint16be_unmarshal(w5500ll_read_sock_reg(chip->spidev, socknum, tx_write_pointer)); - w5500ll_write(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), buf, count); + w5500ll_writev(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, TX), &((struct iovec){ + .iov_base = buf, + .iov_len = count, + }), 1, 0, 0); w5500ll_write_sock_reg(chip->spidev, socknum, tx_write_pointer, uint16be_marshal(ptr+count)); /* Submit the queue. */ w5500_socket_cmd(socket, CMD_SEND); @@ -836,8 +861,8 @@ static ssize_t w5500_udp_sendto(struct _w5500_socket *socket, void *buf, size_t } } -static void w5500_udp_set_read_deadline(struct _w5500_socket *socket, uint64_t ns) { - debugf("udp_conn.set_read_deadline(%"PRIu64")", ns); +static void w5500_udp_set_recv_deadline(struct _w5500_socket *socket, uint64_t ns) { + debugf("udp_conn.set_recv_deadline(%"PRIu64")", ns); ASSERT_SELF(packet_conn, UDP); socket->read_deadline_ns = ns; } @@ -891,7 +916,10 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_ * can't find in the datasheet where it describes * this; this is based off of socket.c:recvfrom(). */ uint8_t hdr[8]; - w5500ll_read(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), hdr, sizeof(hdr)); + w5500ll_readv(chip->spidev, ptr, CTL_BLOCK_SOCK(socknum, RX), &((struct iovec){ + .iov_base = hdr, + .iov_len = sizeof(hdr), + }), 1, 0); if (ret_node) { ret_node->octets[0] = hdr[0]; ret_node->octets[1] = hdr[1]; @@ -905,7 +933,10 @@ static ssize_t w5500_udp_recvfrom(struct _w5500_socket *socket, void *buf, size_ /* Now read the actual data. */ if (count > len) count = len; - w5500ll_read(chip->spidev, ptr+8, CTL_BLOCK_SOCK(socknum, RX), buf, len); + w5500ll_readv(chip->spidev, ptr+8, CTL_BLOCK_SOCK(socknum, RX), &((struct iovec){ + .iov_base = buf, + .iov_len = len, + }), 1, 0); /* Tell the chip that we read the data. */ w5500ll_write_sock_reg(chip->spidev, socknum, rx_read_pointer, uint16be_marshal(ptr+8+len)); w5500_socket_cmd(socket, CMD_RECV); |