113 lines
3.4 KiB
C
113 lines
3.4 KiB
C
// Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
// See LICENSE.md for license information.
|
|
// SPDX-License-Identifier: MIT
|
|
//
|
|
// Minimal headless serial self-test -- NO jlInit (no video/graphics), so it
|
|
// runs even where the graphics HAL can't (e.g. AROS on the Amiga). Opens the
|
|
// DEFAULT port (or SERTEST_DEVICE) at 9600 8N1, sends a banner (TX
|
|
// heartbeat), then echoes every received byte forever. A host serial peer
|
|
// verifies banner (TX) + echo (RX).
|
|
//
|
|
// A peer that sees the modem lines (DOSBox's nullmodem reports them in the
|
|
// byte stream as they change) can also send DTR_CHECK: the program then
|
|
// drops and raises DTR, closes and reopens the port, drops DTR and closes
|
|
// the port for good, with a marker line after each step, so the peer can
|
|
// check that jlSerialSetDtr reaches the line and that jlSerialClose leaves
|
|
// DTR as it is, up or down. After the check the port stays closed.
|
|
#include <joey/serial.h>
|
|
|
|
#define DTR_CHECK 0x04u // ASCII EOT: run the DTR check (not echoed)
|
|
#define DTR_ACK 0x06u // ASCII ACK: the peer has the whole marker line
|
|
|
|
// The port, overridable at build time (-DSERTEST_DEVICE=JL_SERIAL_SLOT
|
|
// -DSERTEST_UNIT=2u) so a gate can open one other than the default.
|
|
#ifndef SERTEST_DEVICE
|
|
#define SERTEST_DEVICE JL_SERIAL_DEFAULT
|
|
#endif
|
|
#ifndef SERTEST_UNIT
|
|
#define SERTEST_UNIT 0u
|
|
#endif
|
|
|
|
static void dtrCheck(const jlSerialConfigT *cfg);
|
|
static void sendMark(const char *text);
|
|
|
|
|
|
static void dtrCheck(const jlSerialConfigT *cfg) {
|
|
jlSerialSetDtr(false);
|
|
sendMark("JLDTR-OFF\r\n");
|
|
jlSerialSetDtr(true);
|
|
sendMark("JLDTR-ON\r\n");
|
|
jlSerialClose();
|
|
if (!jlSerialOpen(SERTEST_DEVICE, cfg)) {
|
|
return;
|
|
}
|
|
sendMark("JLDTR-REOPENED\r\n");
|
|
jlSerialSetDtr(false);
|
|
sendMark("JLDTR-HANGUP\r\n");
|
|
jlSerialClose();
|
|
}
|
|
|
|
|
|
// A marker line, then the peer's DTR_ACK: the line has gone out whole, so
|
|
// the next line change comes after it (a changed line is reported at once,
|
|
// while bytes wait their turn in the UART), and a close cannot throw any of
|
|
// it away.
|
|
static void sendMark(const char *text) {
|
|
uint16_t len;
|
|
uint16_t sent;
|
|
uint8_t byte;
|
|
|
|
len = 0u;
|
|
while (text[len] != '\0') {
|
|
len++;
|
|
}
|
|
sent = 0u;
|
|
while (sent < len) {
|
|
jlSerialPoll();
|
|
sent = (uint16_t)(sent + jlSerialWrite((const uint8_t *)&text[sent], (uint16_t)(len - sent)));
|
|
}
|
|
for (;;) {
|
|
jlSerialPoll();
|
|
if (jlSerialRead(&byte, 1u) == 1u && byte == DTR_ACK) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
jlSerialConfigT cfg;
|
|
static const char banner[] = "JLSERTEST-READY\r\n";
|
|
|
|
cfg.baud = 9600u;
|
|
cfg.dataBits = 8u;
|
|
cfg.stopBits = 1u;
|
|
cfg.parity = JL_SERIAL_PARITY_NONE;
|
|
cfg.flow = JL_SERIAL_FLOW_NONE;
|
|
cfg.unit = SERTEST_UNIT;
|
|
if (!jlSerialOpen(SERTEST_DEVICE, &cfg)) {
|
|
return 1;
|
|
}
|
|
jlSerialWrite((const uint8_t *)banner, (uint16_t)(sizeof(banner) - 1u));
|
|
|
|
for (;;) {
|
|
uint8_t buf[64];
|
|
uint16_t n;
|
|
uint16_t i;
|
|
|
|
jlSerialPoll();
|
|
n = jlSerialRead(buf, (uint16_t)sizeof(buf));
|
|
for (i = 0u; i < n; i++) {
|
|
if (buf[i] == DTR_CHECK) {
|
|
break;
|
|
}
|
|
}
|
|
if (i > 0u) {
|
|
jlSerialWrite(buf, i);
|
|
}
|
|
if (i < n) {
|
|
dtrCheck(&cfg);
|
|
}
|
|
}
|
|
// not reached
|
|
}
|