0
votes

I am writing a simple program to open the serial port /dev/ttyS0 which is visible in /dev.

The code opens the serial port no problems on my PC at home but on my work machine I run into an error that returns "Input/Output Error". The error appears as a result of tcgetattr failing but I am unsure why as the serial port is visible. I added a verbose error printout via libexplain and it reported to me.

tcgetattr(fildes = 3 "/dev/ttyS0", data = 0x7FFEEA8CEEB0) failed, Input/output error (5, EIO)

I am not sure what other information is relevant that I can provide. It is an Arch Linux system with a 5.3.8 kernel.

const char *port_name = "/dev/ttyS0";

int main(int argc, char *argv[])
{
   int serial_fd, file_status;
    struct termios termSettings;
    struct sigaction act = { 0 };

    serial_fd = open(port_name, O_RDWR | O_NOCTTY | O_NONBLOCK);

    if (serial_fd < 0) {
        perror("Opening serial port failed");
        return -1;
    }

    if (tcgetattr(serial_fd, &termSettings) < 0) {
        perror("Getting terminal attributes failed");
        printf("Error reason: %s\n",  explain_tcgetattr(serial_fd, &termSettings));
        goto error;
    }
   ...
}

The complete source is here

1
Looks like a hardware issue. Are you sure you are using the right port? Does dmesg | grep /dev/ttyS0 report something unusual? What driver does your port use?Marcos G.
dmesg is empty, setserial is reporting /dev/ttyS0, UART: unknown, Port: 0x03f8, IRQ: 4. /sys/class/tty/*/device/driver is showing all of my 4 ttyS[0123] being run by the serial8250 driver.Alex Hoffmann
Do a sudo modprobe serial-8250 and try dmesg | grep /dev/tty again. You are on a desktop with a multiport card, right?Marcos G.
lsmod is saying I don't have it in my kernel's /lib/modules even though CONFIG_SERIAL_8250 is enabled in my kernel build. Funnily enough I get the same result from my home PC, saying 8250 cannot be found. Both are thinkpads with docks. My work computer (with the error) is an x280 with a thunderbolt dock.Alex Hoffmann
"In this case does async make sense?" -- No, because the kernel handles the async I/O when you open the serial terminal. Your program is "reading" from a terminal buffer (typically 4K bytes) rather than the hardware. See Linux serial drivers The device driver using interrupts is buffering the received data. Your program can fetch data from the upper-layer buffer at any pace. Preferably use syscalls of more than just one byte.sawdust

1 Answers

2
votes

The dmesg(1) output you show in the comments to your question shows UART: unknown. It seems this can be the problem. It is not recognizing any uart in port 0x3f8, so you seem not to have an uart there (at least, not a standard or compatible one)

The message normally shows UART: ns16550a or similar, giving you info about the chipset installed there. In your case, the other parameters, show as reserved by the kernel so no other device can use those. I don't know the exact reason why the serial driver does not deallocate the resources and continues, but that's probably some legacy issue also.

PC based uarts are normally recognized by hardwired configuration only at fixed locations in the system, and are exercised (some inocuous command is sent to see if it responds to it) to be recognized, as they are legacy devices, predating from PnP or PCI devices, so they must be probed by software at well known places. This is what the software is doing.

If you know there's a physical port device installed, try to use BIOS SETUP to check if the serial port has been enabled in BIOS (if it hasn't you'll not see it at all). Enable it if it hasn't been, and try again.