// 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 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 #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 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(JL_SERIAL_DEFAULT, 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 = 0u; if (!jlSerialOpen(JL_SERIAL_DEFAULT, &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 }