Serial port

There are different names for the serial port of a PC. On the IBM PC they are simply called COM. In the UNIX/Linux world tty (TeleTypewriter) From the electronic point of view they are RS232 connections making use of an UART (Universal asynchronous receiver/transmitter). Nowadays a Sub D 9pin male connector on the PC has become the standard:








Data Carrier Detect




Receive Data




Transmit Data




Data Terminal Ready







Data Set Ready




Request To Send




Clear To Send




Ring Indicator

Working with serial ports

There are two programs to do settings with the ports setserial and stty.

stty -a shows the settings in human readable form and

stty -g in computer readable form, what comes out with it can be used to store current setting and to restore it later. Either what is coming out can be stored in a file or simply passed on command line that can then look as stty -F /dev/ttyUSB0 1:4:da7:a30:3:1c:7f:15:4:10:0:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0

setserial uses a config file /etc/serial.conf.

For the more heavy stuff setserial is used and for the simple things stty

Serial ports have been designed for speeds up to 115200 baud. when exceed ing this baudrate e.g. as setting something for 250000 baud Linux might refuse this.

setserial -a /dev/ttyUSB0

/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0 Baud_base: 24000000, close_delay: 0, divisor: 0 closing_wait: infinte Flags: spd_hi low_latency

Shows that the uart (FTDI chip on USB) has a baudbase frequency of 24MHz.

setserial -a /dev/ttyUSB0 spd_cust

Now it is set for custom speed, verify it setserial -a /dev/ttyUSB0

/dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0 Baud_base: 24000000, close_delay: 0, divisor: 0 closing_wait: infinte Flags: spd_cust low_latency

Calculate the divisor for the as example for the target 250000 baud

divisor= 24MHz / 250000 = 96

then set it and verify setserial -a /dev/ttyUSB0 divisor 96

setserial -a /dev/ttyUSB0 /dev/ttyUSB0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0 Baud_base: 24000000, close_delay: 0, divisor: 96 closing_wait: infinte Flags: spd_cust low_latency

This gets a bit ugly, you need to activate it but stty gets confused and must be made happy by passing a fake baudrate

stty -F /dev/ttyUSB0 38400 stty: /dev/ttyUSB0: unable to perform all requested operations finally test it

stty -F /dev/ttyUSB0

Terminal programs

The user should be in the uucp group to have access to the serial port hardware.

/dev/ttyS0 corresponds to Com1

minicom is the classic RS232 Terminal program that runs in a console. It can be used to connect serial devices. It has an historic user interface and using the default settings, it tries to connect to a modem and dials telephone numbers. It will therefore fail on any other devices that are no modems. To have minicom working on something else than a modem, go to menu item "Modem and dialing" and delete the "Init string" and "Reset string". After that it works as expected.

Ctrl + A to get the status line, then Z will bring up help screen

Type minicom -s to go directly into setup (useful when you have done previously wrong settings).

An alternatives with nicer user interface are gtkterm or moserial. To get something simple there is picocom.

Troubleshooting serial links

It is always a hassle when there is a problem with RS232. Do I have a SW problem? Do I have a cable problem? Is the problem on my local side or the other? Is the driver loaded in the kernel? Has an other program already used it? Has just root permission?

To find out:

  1. Start gtkterm and configure the port

  2. Make a jumper from pin 3 to pin 2 on the sub D 9pol connector. Or better make a plug for that.

  3. Type a character and it echoes back, remove jumper and it does not work. Proof it is not a local echo, the characters went through the cable!

If this does not help there might be a hardware problem. Unfortunately there are many hardware hacks.

  1. The RS232 requires a voltage swing of greater than ±3V and smaller than 12V. This means a negative voltage and a large positive voltage needs to by available by the peripheral device. Simple devices having just a battery have just one single voltage and maybe even to small for creating even a nice positive voltage level. It is possible to create the correct voltages out of a single voltage, but this adds additional cost to peripheral devices: Even chips as the MAX232 might be to costly. Therefore often such devices make use of a hack. They abuse the DTR (pin 4) and the RTS (pin 7) handshake lines as additional (or as the one and only) power supply. This causes the software to initialize those pins correctly to have the device functioning. As example: Simple multi-meters require DTR to have a high and RTS to have a low voltage level on its pins.

  2. Even more radical devices as the simples form of the serial LIRC receiver speculate that an open serial input is considered to have a low level (negative voltage) and therefore produce just the positive level.

Since nobody is proud of those hacks, they are usually bad or not at all documented.The result is bad communication with occasionally data loss or no communication at all.

In a professional environment is a must to respect the RS232 specification and have proper signals.

An other issue is that /dev/ttyS0 belongs to the user root and the uucp group. You are not root so you need to modify /etc/group to put your name to the uucp group. If the uucp group does not exist, you have to add it, however don't do that manually since you probably do not know the number that corresponds to the uucp group. Make a dummy emerge -1 gnokii to have the group in /etc/group created.

USB to RS232 serial controller

Nowadays RS232 ports disappear from PCs, Laptops and the one present are probably already used. Luckily there are USB to RS232 converter cables:

  1. Fist you need to make a kernel that supports your USB serial converter (e.g Prolific Technologies)

  2. Start udevadm monitor --env

  3. Plug it in and check in what udevadm puts on the console:


  1. Check also what is been reported by usbview

  2. Scan trough /dev and notice /dev/ttyUSB0 appears and disappears (udevadm monitor does not point straight to this location).

  3. Start minicom, gtkterm or komport and configure to /dev/ttyUSB0 (no HW handshake)

  4. Test it as described in: Troubleshooting serial links

Programming serial links

To program serial links in c, the termios high level interface should be used. The header file can be found at /usr/include/bits/termios.h.

If some hacked hardware is being used that needs special handling on the control lines, then termios might not be the way to go, since it is written to use the serial link the clean way. Direct hardware access to the UART chip is then the way to go. The definitions of the chip can be found at /usr/include/linux/serial_reg.h. However accessing the hardware directly is normally just available for the kernel, so your code should end up in a device driver.

To get access to the hardware on a root level and not as device driver, the function ioperm needs to be called to get the permission. It checks if this hardware is not occupied by some other program. When programming a device driver modprobe<device driver> would do the same check. To access the hardware afterwards, the functions as inb and outb can be used to write to the chip. Those functions are usually used in kernel module programming. For details see /usr/include/sys/io.h.


You need to set the option -O or -O2 to have the functions inb, outb successfully available, since they are inline makros.

If you want to call this code not as device driver and not as root, you have to get the file the root ownership and you have to set the set user ID flag (s):

chown root:root<my code>

chmod a+s<my code>

This way a user can call this program, but the program will not run under the users ownership, it will use its own ownership that are set as root.

Programming the serial link under python is possible after emerge pyserial. Different example code and the terminal program miniterm come with it.

miniterm is a single python file with around 500 lines of code. It is a good start to write your own code, just delete everything not necessary and then add your own functionality. However you need certain python skills, since miniterm makes use of multi-threading, object oriented programming, termios for the console and optparse for the command line arguments. So if you handle this exercises successfully you can call yourself a python programmer.

Connection to a remote serial link

ser2net allows a remote computer to use a IP port of an other computer to connect its serial link. man ser2net shows the documentation. ser2net is a daemon that has its config file at /etc/ser2net.conf that can have an entry as


This means the server having the serial port and the daemon wait on port 3333 for an income request. They use then the raw mode to pass everything to the serial link. 0 means there is no time out so the connection stays until a power down. an other value would terminate the connection when not traffic for the number of seconds given appears. The rest is self explanatory.

Now a program as telnet need to be used to connect to the remote machines port and than everything is passed to the serial link.

Alternatively the program socat can be used to create a virtual serial link /dev file. When accessing this file then /dev on the remote computer is accessed instead.

The ser2net daemon can be started via init script or systemd

Links are

Linurs Servernest startpage