aboutsummaryrefslogtreecommitdiff
path: root/src/net/ps1
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-09-27 17:03:06 +0200
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2022-11-01 16:26:16 +0100
commit980858186149651df5543b6fc99a4f7db0cdd089 (patch)
treed347200b0a562d84df505097651ad0642f207fdd /src/net/ps1
parent39f50e601d395bbd2d78d0147ac530b756da2fff (diff)
downloadjancity-980858186149651df5543b6fc99a4f7db0cdd089.tar.gz
WIP
Diffstat (limited to 'src/net/ps1')
-rw-r--r--src/net/ps1/src/net.c238
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;
}