diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2022-09-27 17:03:06 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2022-11-01 16:26:16 +0100 |
| commit | 980858186149651df5543b6fc99a4f7db0cdd089 (patch) | |
| tree | d347200b0a562d84df505097651ad0642f207fdd /src/net/ps1 | |
| parent | 39f50e601d395bbd2d78d0147ac530b756da2fff (diff) | |
| download | jancity-980858186149651df5543b6fc99a4f7db0cdd089.tar.gz | |
WIP
Diffstat (limited to 'src/net/ps1')
| -rw-r--r-- | src/net/ps1/src/net.c | 238 |
1 files changed, 219 insertions, 19 deletions
diff --git a/src/net/ps1/src/net.c b/src/net/ps1/src/net.c index 8c037f3..af964cf 100644 --- a/src/net/ps1/src/net.c +++ b/src/net/ps1/src/net.c @@ -1,39 +1,233 @@ #include <net.h> #include <net/serial.h> -#include <errno.h> +#include <net_serial_private.h> +#include <transport.h> +#include <psx.h> +#include <psxsio.h> #include <stdbool.h> #include <stddef.h> +#include <stdio.h> -int net_read(struct net_socket *const h, void *const buf, const size_t n) +static struct net_host { - return -1; + enum net_role role; + bool used, sending; + struct transport_handle h; + struct net_event ev; + + struct net_host_fifo + { + char buf[32]; + size_t pending, read; + } in, out; +} host; + +enum {TX_INT_ENABLE = 1 << 10}; + +int net_write(struct net_host *const h, const net_peer peer, + const void *const buf, size_t n) +{ + return transport_send(&h->h, buf, n); } -int net_write(struct net_socket *const h, const void *const buf, const size_t n) +int net_close(struct net_host *const h) { - return -1; + SIOStop(); + RemoveSIOHandler(); + h->used = false; + return 0; +} + +static void send_byte(struct net_host *const h) +{ + struct net_host_fifo *const f = &h->out; + + if (f->pending != f->read) + { + if (SIOCheckOutBuffer()) + { + size_t new = f->read + 1; + + if (new >= sizeof f->buf) + new = 0; + + h->sending = true; + SIOSendByte(f->buf[f->read = new]); + } + } + else + { + h->sending = false; + SIO_CTRL &= ~TX_INT_ENABLE; + } } -int net_close(struct net_socket *const h) +int net_update(struct net_host *const h) { - return -1; + return transport_update(&h->h); } -int net_update(struct net_socket *const h) +static void on_received(const struct transport_event *const ev, + void *const arg) { - return -1; + struct net_host *const h = arg; + + net_serial_on_received(ev, &h->ev); } -struct net_socket *net_connect(const union net_connect *const c) +static int on_write(const void *const buf, size_t n, void *const arg) { - return NULL; + const size_t orig = n; + struct net_host *const h = arg; + + EnterCriticalSection(); + + for (const char *b = buf; n; n--, b++) + { + struct net_host_fifo *const f = &h->out; + size_t new = f->pending + 1; + + if (new >= sizeof f->buf) + new = 0; + + if (new == f->read) + { + fprintf(stderr, "%s: out FIFO full\n", __func__); + goto end; + } + + f->buf[f->pending = new] = *b; + } + + if (n != orig) + SIO_CTRL |= TX_INT_ENABLE; + +end: + ExitCriticalSection(); + return orig - n; +} + +static int on_read(void *const buf, const size_t n, void *const arg) +{ + size_t rem = n; + struct net_host *const h = arg; + struct net_host_fifo *const f = &h->in; + + EnterCriticalSection(); + + for (char *b = buf; rem; rem--, b++) + { + if (f->read == f->pending) + goto end; + + size_t new = f->read + 1; + + if (new >= sizeof f->buf) + new = 0; + + *b = f->buf[f->read = new]; + } + +end: + ExitCriticalSection(); + return n - rem; +} + +static struct transport_cfg get_transport_cfg(void) +{ + return (const struct transport_cfg) + { + .arg = &host, + .received = on_received, + .read = on_read, + .write = on_write + }; } -struct net_socket *net_server(const union net_server *const c) +static void on_byte_received(struct net_host *const h, const char ch) { + struct net_host_fifo *const f = &h->in; + size_t new = f->pending + 1; + + if (new >= sizeof f->buf) + new = 0; + + f->buf[f->pending = new] = ch; +} + +static void sio(void) +{ + struct net_host *const h = &host; + + if (SIOCheckInBuffer()) + on_byte_received(h, SIOReadByte()); + + send_byte(h); +} + +static void start_sio(const unsigned long baud) +{ + enum + { + RX_INT_MODE_1_BYTE = 1 << 8, + RX_INT_ENABLE = 1 << 11 + }; + + SIOStartEx(baud, SIO_DATA_LEN_8, SIO_PARITY_NONE, SIO_STOP_BIT_1); + SetSIOHandler(sio); + SIO_CTRL |= RX_INT_ENABLE | RX_INT_MODE_1_BYTE; +} + +struct net_host *net_connect(const union net_connect *const c) +{ + struct net_host *const h = &host; + + if (h->used) + goto failure; + + start_sio(c->serial.cfg.baud); + + *h = (const struct net_host) + { + .role = NET_ROLE_CLIENT, + .used = true, + .h = + { + .cfg = get_transport_cfg() + } + }; + + if (transport_connect(&h->h)) + goto failure; + + return h; + +failure: + net_close(h); return NULL; } +struct net_host *net_server(const union net_server *const c) +{ + struct net_host *const h = &host; + + if (h->used) + return NULL; + + *h = (const struct net_host) + { + .role = NET_ROLE_SERVER, + .used = true, + .h = + { + .cfg = get_transport_cfg() + } + }; + + start_sio(c->serial.cfg.baud); + return h; +} + int net_init(void) { return 0; @@ -43,18 +237,24 @@ void net_deinit(void) { } +int net_set_event(struct net_host *const h, + const struct net_event *const ev) +{ + h->ev = *ev; + return 0; +} + bool net_available(const enum net_domain d) { return d == NET_DOMAIN_SERIAL; } -const char *const *net_serial_devices(size_t *const n) +bool net_serial_unique(void) { - static const char *const dev[] = - { - "PS1 port" - }; + return true; +} - *n = sizeof dev / sizeof *dev; - return dev; +enum net_role net_role(const struct net_host *s) +{ + return s->role; } |
