4

I work with cash registers that are bare-boned RedHat Linux boxes. These registers have a scanner attached to a serial port (ttyS0).

We do a lot of testing that requires someone to stand at the register and swipe products across the scanner. I'm trying to figure out a way to remove the person from the equation.

Is there an easy way to simulate input FROM the serial port?

Obviously, sending information TO the serial port is easy:

echo [whatever] > /dev/ttyS0

but what I'd really love is some sort of bash code where I could type:

echo [barcode number] > (some code that makes the machine think the barcode number is coming from the serial port)

Is this possible?

I'm also restricted in what I can actually put on the register. I can't install any new utilities onto the machine. I can put bash scripts on there, but that's about it.

AdminBee
  • 22,803
  • 5
    Can the software work with any character device? If yes, then you could use a simple named pipe (mkfifo) instead of ttyS0. – filo Mar 01 '20 at 17:12

3 Answers3

7

You can do that (as root) with the TIOCSTI ioctl. See the example program at the end of this answer. Use it as

echo [whatever] | ./tiocsti > /dev/ttyS0

You can also do that from perl without having to compile anything -- search this site, there are plenty of examples.

Another option that I am using, is doing it in hardware: simply connect the machine to itself via an USB->serial adapter, and write to the /dev/ttyUSBx (or /dev/serial/by-id/xx-xx-xx) whatever you want read from /dev/ttySx (make /dev/ttyUSBx raw with stty raw so it does pass the data unchanged).

  • I tried it, but it give an error " bash: ./tiocsti: No such file or directory bash: echo: write error: Broken pipe " – Fitri Halim Mar 01 '20 at 10:36
  • tiocsti is supposed to be the program you compiled via cc tiocsti.c -o tiocsti. But I strongly recommend the "serial loopback" solution, because that will allow you to test it in the same environment as in the production. And BTW: why have you the SIGPIPE ignored in your shell? echo to a broken pipe should be killed silently, not print "write error: Broken pipe". –  Mar 01 '20 at 10:40
  • what is seriial loopback solution? – Fitri Halim Mar 01 '20 at 11:01
  • To use a USB->serial adapter to connect your machine to itself, as described in the answer. Notice that you could compile that tiocsti.c program on another machine and copy it to your bare-bones machine; it's self contained and only depends on the C library. –  Mar 01 '20 at 11:05
  • Oh, you mean connect my machine to itself using a USB adapter! And how do I compile the tiocsti.c code, do I need to compile it using dev? Sorry I am a total novice, need to learn more – Fitri Halim Mar 01 '20 at 12:20
  • Yes, you need a compiler and the libc development packages (eg. dnf install gcc glibc-devel, apt-get install gcc libc6-dev or similar on a distro which is not newer than that where the program should run). –  Mar 01 '20 at 12:31
  • I try the serial loopback solution and gladly I can re-read the data that I sent .I tried something like cat "123456789101112\n\r > dev\USBx and able to read it back in another terminal using cat \dev\ttyS0 . However my Java GUI doesn't respond to it. My Java GUI has already been programmed to read barcode input from ttyS0 serial port . What is the correct string that is normally sent by an RS232 barcode scanner into PC Serial Port? – Fitri Halim Mar 02 '20 at 08:50
  • Thank you very much, finally got it to works using TIOCSTI method! – Fitri Halim Mar 03 '20 at 07:56
7

TIOCSTI is available, but that's not a highly regarded mechanism nowadays. An alternative is very simple: this is what pseudo-terminals do. Just point the scanner at a pseudo-terminal instead of the real serial terminal, and drive the appropriate input from the pseudo-terminal's master side. Indeed, expect comes ready-made for driving an interactive terminal I/O application via a pseudo-terminal.

It all depends from whether expect, which is in a Fedora package, is one of the things that the people who installed everything chose to have already installed on your machine. That's also true of Perl, of course. We answerers have no way of knowing what the vague "bare boned" actually entails.

JdeBP
  • 68,745
3

Finally I am able to solve it. Thank you very much guys.

  1. Create a blank text file

  2. Edit the file and copy and paste this code into the text file

//**tiocsti.c**//

#include <unistd.h>`
#include <err.h>

int main(void)
{
            char c; ssize_t r;
    while((r = read(0, &c, 1)) > 0)
    {
                    if(ioctl(1, TIOCSTI, &c)) 
        {   
            err(1, "ioctl(TIOCSTI)");
        }       
    }   
        if(r < 0)
    err(1, "read");
            return 0;
}
  1. Save the text file as tiocsti.c

  2. On the same directory, run cc tiocsti.c -o tiocsti on your terminal to compile the tiocsti.c file you created in the first step

5.To generate fake input into ttyS0, simply run

echo yadayada | ./tiocsti > /dev/ttyS0