Send file over serial port with Linux and C
I’m developing an application that reads data from a serial port and sends it over a TCP connection, and vice versa. Unfortunately, while reading data from serial port, it never stops. It does not detect EOF mark, nor EOL or some other special character. So, how could i detect an end of file (or «end of connection») over serial port in C and Linux?
How much control do you have over the device connected to the serial port? What about the device at the other end of the TCP socket?
How do you decide when to write data to the TCP socket? That is, are you trying to receive the entire data set before transmitting via the socket, or are you reading data from the socket and immediately (or slightly buffered) writing it to the socket?
5 Answers 5
Depends on how much control you have over the protocol used for the serial link. Unless the files implicitly include some end-of-file marker (and as I’ve understood your post they don’t), you need to implement some kind of communication protocol in order to transfer files.
Some of the most simple procols used way back in the BBS days were XMODEM and it’s derivatives. They may be simple enough for you to use.
If you have a full-blown computer at the other end of the serial line, it would probably be far simpler just to set up an PPP link over the serial line and do the communication over TCP/IP.
Serial link only sends bytes. There is no packet frame, no error checking so you can’t send files reliably over raw serial link. You need to use some protocol like XMODEM, KERMIT etc.
It’s not trivial to implement such protocol. It may be easier to run TCP/IP over the link if the other end is also a computer. Please check out SLIP or PPP.
The serial port gives «end of file» on a hangup condition, which is signalled out-of-band by the modem control lines (dropping of DCD ). If you’re connected with a null-modem, that’ll never happen.
Use a framing mechanism, like the other answers have suggested. You may not need to go the whole hog with something like ZMODEM though — just prefixing your file with the file size and a CRC32 checksum should do, if the link is reasonably error-free and 8-bit clean.
Check your serial port configuration:
Set cooked link instead of raw link:
cheap and dirty solution: on linux, unix or osx just run ‘screen -L ‘. At the other end write the output of your file to the console, in raw mode. -L logs it to a file the contents of which will be the file you transfered from the other end. Check the contents with xxd to verify they match what you had at the source.
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.12.43529
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
File transfer over a serial line
I have 2 linux computers, and a serial line between them, one of them is only accessible through a serial line that has shell on it. How can I transfer files between the 2 computers? I’ve heard that it can be done with some rz/sz magic. Can I do the same trick with a pseudo-terminal instead of other computer?
6 Answers 6
You need a terminal application like minicom. Then you connect the two computers, start minicom on one side, connect to the other side (the one where you can login) and use the sz command to send the file. Minicom will automatically detect the file transfer. Note that you might need to install the sz command on the login machine, how that is done is dependent on your distribution.
Copying txwikinger’s answer, I would use kermit, the grandfather of file transfer programs. We used it in the 80’s, long before there was Linux. Wikipedia suggests it may be better than zmodem (sz).
An alternative approach is to use SLIP or PPP, as suggested by Axel. But this howto for PPP is about 15 years old.
You could make use of the «Serial Line Internet Protocol» as described here.
Once two systems are interconnected by a slip line, you can use any IP-based tool (ftp, rcp, scp, ssh, . ) to exchange files. It probably takes too long to configure for a once-only purpose but might be worth looking at for embedded systems with RS232 port or old systems from a pre-LAN aera.
My way of transferring a file.bin via serial connection is to use openSSL tool since I don’t have other options to do base64 encoding and back:
openssl enc -base64 file.b64
openssl enc -base64 -d file.bin
I’ve run into the same issue and all I had was a prompt, but no network modules loaded, no rz/sz binaries, nor anything else in the target system I could make use of in order to transfer files.
But I had echo and I found a solution where everything needed was — yes — echo .
I came across serio, a very simple, clever and open source Python script (available here: https://github.com/devttys0/serio). All this tiny gem does is to echo every single byte from the source file onto the target’s shell using echo and redirecting the output to a destination file.
So, first I needed to provide a shell on target (I did it using minicom ), then leave minicom and issue something like this from the host machine:
./serio.py \ -s /path/to/input/file/in/host.bin \ -d /path/to/destination/on/target.bin \ -p /dev/ttyUSB0
The only requirements on the embedded system is that it provides an interactive shell on the serial port, and that the shell’s echo command supports the -n and -e options.
The transfer is, of course, very slow, but it will hopefully solve my issue.
How to send data to a serial port and see any answer?
On Linux, I want to send a command string (i.e. some data) to a serial port (containing control characters), and listen to the response (which also usually might contain control characters). How can I do this as simplest as possible on Linux? An example is appreciated!
5 Answers 5
All devices on Unix are mapped to a device file, the serial ports would be /dev/ttyS0 /dev/ttyS1 . .
First have a look at the permissions on that file, lets assume you are using /dev/ttyS1 .
You will want read.write access, if this is a shared system then you should consider the security consequences of opening it up for everyone.
A very simple crude method to write to the file, would use the simple echo command.
You can have cat running in one terminal, and echo in a 2nd.
If everything is gibberish, then baud rate, bit settings might need setting before you start sending. stty will do that. !! NOTE stty will use stdin as default file descriptor to affect.
This might be enough for you to script something and log ? Not sure what you are trying to achieve.
For a more interactive, remembers your default settings approach would be to use minicom it is just a program which does everything I’ve mentioned so far. (similar to hyperterminal in Windows, you might be familiar).
An intermediate solution, would use a terminal program like screen which will work on a serial device.
man screen man minicom man stty for more information
Receiving data from Serial Port
I want to receive data from RS232 Serial port to my terminal and with a directive to a file. It should be pretty straight forward.
cat /dev/ttyS0 cat /dev/ttyS0 > file.txt
sudo stty -F /dev/ttyS0 9600 -parity cs8 cstopb
But I don’t receive anything on the terminal.It’s just blank. What is the problem?
1 Answer 1
Try Minicom first and see what your serial port returns. Install it with sudo apt-get install minicom
You start it as follows (for ttyS0):
You can set the communication parameters from within Minicom (using ctrl-A P ), so you’re sure that they are correct.
If your device uses a specific protocol, it might need a command to start its communication. So have a look at the user manual.
Maybe your device is set up to use hardware handshaking. If possible, turn it off (at least to start with).
If you can’t turn it off, then you will have to set that up as well on your side. In Minicom this is under ctrl-A O and then serial port setup .
I’ve used Minicom often to debug serial communications and I find it works best.
I’ve received some more information from the OP:
The laboratory instrument(Cobas C311) uses ASTM protocol. There in the interface , we just need to click «Send to Host» and it sends a bunch of ASTM records. I just need to receive them in a file. Is there any other setting? What is the command to start acquiring data. and how to save the data in a file?
Chosen the right paramters. Minicom is showing 9600 8N2. Hope it’s alright. But receiving nothing — not a single bit. The analyser says, «The instrument transmitted ENQ as a send request,but the Host did not return ACK or NAK within 15 seconds.(Link Timeout)»
The device uses the ASTM Protocol. The device sends the character as a signal that it is ready to start sending data.
This is not something you will be able to receive using minicom or any other terminal program. You will need proper application software that supports this protocol.
You definitely have to read your user manual and check the installation disk (if any) and the manufacturer’s website for an application that supports this protocol.
I would be surprised if they don’t have application support for this device. If they offer something it is likely to be a Windows application or some example code plus a library.
It is possible to write something yourself, but it won’t be easy. There is some Python support for ASTM and there is a Perl script that you could try.
SO also has a post with some information about ASTM..