' The MIT License (MIT)
'
' Copyright (C) 2026 Scott Duensing
'
' Permission is hereby granted, free of charge, to any person obtaining a copy
' of this software and associated documentation files (the "Software"), to
' deal in the Software without restriction, including without limitation the
' rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
' sell copies of the Software, and to permit persons to whom the Software is
' furnished to do so, subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included in
' all copies or substantial portions of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
' FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
' AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
' LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
' FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
' IN THE SOFTWARE.

' comm.bas -- Serial Communications Library for DVX BASIC
'
' Three tiers of serial communication:
'
'   1. Raw serial (SerXxx) -- direct UART I/O with ISR-driven ring
'      buffers. No framing or error correction. Use this for talking
'      to existing BBSs, modems, and other plain serial devices.
'
'   2. Packet serial (CommXxx) -- adds HDLC framing, CRC-16 checksums,
'      and Go-Back-N ARQ for reliable delivery. Data is split into
'      packets and retransmitted on error. Requires both sides to
'      speak the same protocol.
'
'   3. Encrypted serial (CommHandshake + encrypt flag) -- adds DH key
'      exchange and XTEA-CTR encryption on top of packets. Use
'      CommSend with encrypt=True after CommHandshake.
'
' Usage: Add this file to your project.

' UART types (returned by SerGetUart)
CONST SER_UART_NONE   = 0
CONST SER_UART_8250   = 1
CONST SER_UART_16450  = 2
CONST SER_UART_16550  = 3
CONST SER_UART_16550A = 4

' Handshake modes (for SerOpen / CommOpen)
CONST SER_HANDSHAKE_NONE    = 0
CONST SER_HANDSHAKE_XONXOFF = 1
CONST SER_HANDSHAKE_RTSCTS  = 2
CONST SER_HANDSHAKE_DTRDSR  = 3

DECLARE LIBRARY "basrt"

    ' =========================================================
    ' UART Detection and Configuration
    ' =========================================================

    ' Detect the UART type for a COM port (1-4) WITHOUT opening it.
    DECLARE FUNCTION SerGetUart(BYVAL com AS INTEGER) AS INTEGER

    ' Set the I/O base address for a COM port before opening.
    ' Default bases: COM1=&H3F8, COM2=&H2F8, COM3=&H3E8, COM4=&H2E8
    DECLARE SUB SerSetBase(BYVAL com AS INTEGER, BYVAL ioBase AS INTEGER)

    ' Set the IRQ for a COM port before opening.
    ' Default IRQs: COM1=4, COM2=3, COM3=4, COM4=3
    DECLARE SUB SerSetIrq(BYVAL com AS INTEGER, BYVAL irq AS INTEGER)

    ' Get the I/O base address for a COM port.
    DECLARE FUNCTION SerGetBase(BYVAL com AS INTEGER) AS INTEGER

    ' Get the IRQ for a COM port.
    DECLARE FUNCTION SerGetIrq(BYVAL com AS INTEGER) AS INTEGER

    ' =========================================================
    ' Raw Serial I/O (no framing, no error correction)
    ' =========================================================

    ' Open a raw serial port. Returns True on success.
    DECLARE FUNCTION SerOpen(BYVAL com AS INTEGER, BYVAL baud AS LONG, BYVAL dataBits AS INTEGER, BYVAL parity AS STRING, BYVAL stopBits AS INTEGER, BYVAL handshake AS INTEGER) AS INTEGER

    ' Close a raw serial port.
    DECLARE SUB SerClose(BYVAL com AS INTEGER)

    ' Write a string to the serial port. Returns True on success.
    DECLARE FUNCTION SerWrite(BYVAL com AS INTEGER, BYVAL payload AS STRING) AS INTEGER

    ' Read pending data from the serial port. Returns "" if none available.
    DECLARE FUNCTION SerRead$(BYVAL com AS INTEGER) AS STRING

    ' Return the number of bytes waiting in the receive buffer.
    DECLARE FUNCTION SerAvailable(BYVAL com AS INTEGER) AS INTEGER

    ' Clear the receive buffer.
    DECLARE SUB SerFlush(BYVAL com AS INTEGER)

    ' Attach a raw serial port to a Terminal widget.
    DECLARE SUB SerAttach(BYVAL com AS INTEGER, BYVAL termCtrlName AS STRING)

    ' Detach a raw serial port from a Terminal widget.
    DECLARE SUB SerDetach(BYVAL com AS INTEGER)

    ' =========================================================
    ' Packet Serial (reliable delivery + channel multiplexing)
    ' =========================================================

    ' Open a packet serial link. Returns a handle (>0), or 0 on failure.
    DECLARE FUNCTION CommOpen(BYVAL com AS INTEGER, BYVAL baud AS LONG, BYVAL dataBits AS INTEGER, BYVAL parity AS STRING, BYVAL stopBits AS INTEGER, BYVAL handshake AS INTEGER) AS INTEGER

    ' Close a packet serial link.
    DECLARE SUB CommClose(BYVAL handle AS INTEGER)

    ' Send data on a logical channel (0-127).
    ' encrypt: True to encrypt (requires CommHandshake first).
    DECLARE FUNCTION CommSend(BYVAL handle AS INTEGER, BYVAL payload AS STRING, BYVAL channel AS INTEGER, BYVAL encrypt AS INTEGER) AS INTEGER

    ' Receive pending data from a specific channel. Returns "" if none.
    DECLARE FUNCTION CommRecv$(BYVAL handle AS INTEGER, BYVAL channel AS INTEGER) AS STRING

    ' Poll for incoming packets. Call periodically if not using CommAttach.
    DECLARE FUNCTION CommPoll(BYVAL handle AS INTEGER) AS INTEGER

    ' Return the number of unacknowledged packets in the transmit window.
    DECLARE FUNCTION CommPending(BYVAL handle AS INTEGER) AS INTEGER

    ' =========================================================
    ' Encryption (DH key exchange + XTEA-CTR)
    ' =========================================================

    ' Perform Diffie-Hellman key exchange. Blocks until both sides
    ' complete. After this, CommSend with encrypt=True will encrypt.
    DECLARE FUNCTION CommHandshake(BYVAL handle AS INTEGER) AS INTEGER

    ' Check if the key exchange is complete.
    DECLARE FUNCTION CommIsReady(BYVAL handle AS INTEGER) AS INTEGER

    ' =========================================================
    ' Terminal Widget Integration
    ' =========================================================

    ' Attach a packet link to a Terminal widget on a given channel.
    ' encrypt: True to encrypt terminal traffic.
    DECLARE SUB CommAttach(BYVAL handle AS INTEGER, BYVAL termCtrlName AS STRING, BYVAL channel AS INTEGER, BYVAL encrypt AS INTEGER)

    ' Detach a packet link from a Terminal widget.
    DECLARE SUB CommDetach(BYVAL handle AS INTEGER)
END DECLARE
