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.
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 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:
struc __kernel_termios .c_iflag: resd 1; input mode flags .c_oflag: resd 1; output mode flags .c_cflag: resd 1; control mode flags .c_lflag: resd 1; local mode flags .c_line: resb 1; line discipline .c_cc: resb 32; control characters endstruc
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.