From c4b9a1b1c4f8c211f765a089b34b66a2d046f3be Mon Sep 17 00:00:00 2001 From: user Date: Fri, 17 Jul 2026 01:39:29 +0200 Subject: net: chat client - async receive + OSK send over the link port The application layer of the link-port demo, and it ties the whole system together: the LCD terminal displays, the on-screen keyboard types, and the link port carries a live chat. Kernel: sys_srecv_nb (non-blocking link receive; A=byte, CF=none) and sys_pollin (poll the OSK for a typed char without blocking) - syscalls 31/32. Both are what a poll loop needs to receive and type at once. Userland: c/chat.c runs a poll loop - it feeds non-blocking bytes through a SLIP receive state machine and prints whole incoming frames as messages, while pollin() drives the on-screen keyboard; SELECT shows the keys, type a line, START sends it as a frame. libc srecv_nb()/pollin(). Host: tools/gateway.py --mode chat is a simple bot peer (echoes each GB message and injects a few async ones); --keys can drive the OSK for tests. Verified: the gateway pushes 'welcome', ' hey gameboy!', ' nice link cable' unprompted and the GB displays all three (async receive); typing 'hi' on the OSK echoes it and emits the SLIP frame \xC0hi\xC0 (send). A Game Boy in the chat, keyboard on screen, over the link cable. --- c/chat.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 c/chat.c (limited to 'c/chat.c') diff --git a/c/chat.c b/c/chat.c new file mode 100644 index 0000000..987b336 --- /dev/null +++ b/c/chat.c @@ -0,0 +1,57 @@ +#include "netlib.h" +/* chat: a link-port chat client. Incoming SLIP frames from the host gateway + print as messages; SELECT brings up the on-screen keyboard, type a line and + press START to send it. A poll loop interleaves receiving and typing so + messages arrive while you're not mid-line. */ + +static char rxbuf[96]; +static unsigned char rxlen, rxin, rxesc; + +/* feed one non-blocking byte to the SLIP receiver; returns a frame length when + a whole frame has arrived (copied into out), else 0. */ +static unsigned char slip_poll(char *out) { + int b = srecv_nb(); + unsigned char c, i, n; + if (b < 0) return 0; + c = (unsigned char)b; + if (c == SLIP_END) { + if (rxin && rxlen) { + n = rxlen; + for (i = 0; i < n; i++) out[i] = rxbuf[i]; + rxlen = 0; rxin = 0; rxesc = 0; + return n; + } + rxin = 1; rxlen = 0; rxesc = 0; + return 0; + } + if (!rxin) return 0; + if (rxesc) { + if (c == SLIP_ESC_END) c = SLIP_END; + else if (c == SLIP_ESC_ESC) c = SLIP_ESC; + rxesc = 0; + } else if (c == SLIP_ESC) { rxesc = 1; return 0; } + if (rxlen < 96) rxbuf[rxlen++] = (char)c; + return 0; +} + +void main(void) { + char line[64], frame[96]; + unsigned char linelen = 0, n, i, c; + puts("chat: SELECT=keyboard START=send"); nl(); + for (;;) { + n = slip_poll(frame); /* incoming message? */ + if (n) { + for (i = 0; i < n; i++) putc(frame[i]); + nl(); + } + c = pollin(); /* typed a key? */ + if (c == '\n') { + if (linelen) { slip_send(line, linelen); linelen = 0; } + } else if (c == 8) { + if (linelen) { linelen--; putc(8); } + } else if (c) { + if (linelen < 63) { line[linelen++] = (char)c; putc((char)c); } + } + yield(); + } +} -- cgit v1.3.1-sl0p