Serial and parallel ports

For some programs, using the sole processor or the devices inside the computer is not enough. Sometimes there is need to connect to an external device like a modem or a printer. This article will tell you how to achieve this.

Parallel ports

(skip parallel ports)

Here things are simple. Parallel ports don't need any settings, maybe apart from the mode of operation (set inside BIOS). Working with parallel ports under Linux comes to reading and writing to special files - /dev/parportN (N - number), which represent the parallel ports.

Serial ports

Serial ports are harder to program. Sometimes reading and writing to special files is enough, just like for parallel ports, but sometimes this may not suffice. This is because serial ports have their settings:

The first step is opening the special device file, usually /dev/ttySx (x - number).

If port parameters need to be set, use the sys_ioctl system call (number 54). In this case it takes 3 parameters:

First you need to get the current parameters, then change the one you need and send the resulting parameters to the port. Below is some example code in NASM syntax. This code first opens the port file, then it reads the current parameters and sets some new ones:

All the used constants can be found in /usr/include/bits/termios.h. I recommend reading that file, because you can find many interesting flags inside, like automatic translation of CR characters to LF and the other way round.

	mov	eax, 5		; open the file
	mov	ebx, port	; name
	mov	ecx, 402o	; read and write, not controlling terminal
	mov	edx, 777o	; rwx for all
	int	80h

	cmp	eax, 0
	jl	koniec
	mov	ebx, eax	; EBX = descriptor

	; get and set port parameters
%define TCGETS 0x00005401
%define TCSETS 0x00005402

	mov	eax, 54		; sys_ioctl
	;ebx = descriptor
	mov	ecx, TCGETS	; get parameters
	mov	edx, termios
	int	80h

	cmp	eax, 0
	jl	koniec

%define B115200  0010002o
%define CS8   0000060o
%define CLOCAL  0004000o
%define CREAD   0000200o
	mov dword [termios+__kernel_termios.c_cflag],B115200|CS8|CLOCAL|CREAD
%define INPCK   0000020o
	mov	dword [termios+__kernel_termios.c_iflag], INPCK
	mov	dword [termios+__kernel_termios.c_oflag], 0
%define ICANON  0000002o
	mov	dword [termios+__kernel_termios.c_lflag], ICANON
%define VKILL 3
%define VMIN 6
	mov	byte [termios+__kernel_termios.c_cc+VKILL], 0
	mov	byte [termios+__kernel_termios.c_cc+VMIN], 1

	mov	eax, 54		; sys_ioctl
	;ebx = descriptor
	mov	ecx, TCSETS	; set parameters
	mov	edx, termios
	int	80h

	cmp	eax, 0
	jnl	ioctl_set_ok
section .data
port		db	"/dev/ttyS0", 0
termios		istruc	__kernel_termios

After this code you can normally read and write to the device like to a normal file.

One thing needs attention: the 402o value in ECX prior to opening the file. It tells the kernel that we want read and write access, but also the O_NOCTTY (400o) flag is set. It makes the device opened NOT become the program's controlling terminal. In other case reading the standard input may end in reading from the chosen serial port and trying to print a string could send the bytes of the string to the port.

I recommend reading the Serial Programming HOWTO.

On-line contents (Alt+2)
Helpers for people with disabilities (Alt+0)