This is an old revision of the document!
Using serial ports in Linux
by Richard Russell, March 2022
In both Windows and Linux-derived operating systems serial ports are treated like files, i.e. to read data from a serial port you would use INPUT# or BGET# etc. and to write data to a serial port you would use PRINT# or BPUT# etc. Apart from the fact that serial ports are typically much slower than files, you access them the same way.
However serial ports differ from files in two important respects. Firstly they require configuring before use (for example to set the baud rate, number of bits, parity etc.) and secondly you cannot rely on input data being immediately available to read.
With a file you can generally assume that, until the end-of-file is reached, any amount of data can be read (although there may be a delay when accessing a network drive), but with a serial port you may have to wait an indefinite period for incoming data to arrive.
So to avoid your BASIC program 'blocking' in a statement like INPUT# whilst it waits for data to arrive, there needs to be some way to test how much data is 'waiting' in an input buffer. Then the program can continue to perform useful tasks whilst it waits.
BBC BASIC for Windows provides built-in features to configure a serial port (as an extension of the OPENUP function) and to test for how much data is waiting in an input buffer (EXT# function), but BBC BASIC for SDL 2.0 does not (because SDL 2.0 itself, which BBCSDL relies on to provide the cross-platform abstraction layer, doesn't).
To configure and open a serial port in Linux you should use code similar to the following (in this case the port /dev/ttyUSB0 is being configured for 1 stop bit, 8 data bits, no parity and a speed of 9600 baud):
OSCLI "ldattach -1 -8 -n -s 9600 0 /dev/ttyUSB0" OSCLI "stty -F /dev/ttyUSB0 9600 raw" serial% = OPENUP("/dev/ttyUSB0.")
To test how much data is 'waiting' in an input buffer, and can therefore be read safely without blocking, use a function similar to this:
DEF FNavail(N%) LOCAL F% SYS "fileno", @hfile%(N%)!28 TO F% SYS "ioctl", F%, &541B, ^N% : REM FIONREAD = N%