Serial port determinism - linux

This seems like a simple question, but it is difficult to search for. I need to interface with a device over the serial port. In the event my program (or another) does not finish writing a command to the device, how do I ensure the next run of the program can successfully send a command?
Example:
The foo program runs and begins writing "A_VERY_LONG_COMMAND"
The user terminates the program, but the program has only written, "A_VERY"
The user runs the program again, and the command is resent. Except, the device sees "A_VERYA_VERY_LONG_COMMAND," which isn't what we want.
Is there any way to make this more deterministic? Serial port programming feels very out-of-control due to issues like this.

The required method depends on the device.
Serial ports have additional control signal lines as well as the serial data line; perhaps one of them will reset the device's input. I've never done serial port programming but I think ioctl() handles this.
There may be a single byte which will reset, e.g. some control character.
There might be a timing-based signal, e.g. Hayes command set modems use “pause +++ pause”.
It might just reset after not receiving a complete command after a fixed time.
It might be useful to know whether the device was originally intended to support interactive use (serial terminal), control by a program, or both.

I would guess that if you call write("A_VERY_LONG_COMMAND"), and then the user hits Ctrl+C while the bytes are going out on the line, the driver layer should finish sending the full buffer. And if the user interrupts in the middle of the call, the driver layer will probably just ignore the whole thing.
Just in case, when you open a new COM port, it's always wise to clear the port.
Do you have control over the device end? It might make sense to implement a timeout to make the device ignore unfinished or otherwise corrupt packets.

The embedded device should be implemented such that you can either send an abort/clear/break character that will dump the contents of its command buffer and give you a clean slate on your client app startup.
Or else it should provide a software reset character which will reset the command buffer and all state.
Or else it so be designed so that you can send a command termination (perhaps a newline, etc, depending on command protocol) and possibly have an error generated on the parsing of a garbled partial command that was in its buffer, query/clear the error, and then be good to go.
It wouldn't be a bad idea upon connection of your client program to send some health/status/error query repeatedly until you get a sound response, and only then commence sending configuration or operation commands. Unless you can via a query determine that the device was left in a suitable state, you probably want to assume nothing and configure it from scratch, after a configuration reset if available.

Related

Cannot implement custom keyboard in u-boot

As known, u-boot loader supports some sort of "input device system" that allows to register a set of functions (like getc, tstc, start, etc...). So I need to implement my own hardware-specific "keyboard". What should I do? Sounds simple:
1) Create at least "init", "tstc", "getc" and "start" functions in driver file.
2) In "init" call "stdio_register" to let system know about my device.
3) Call driver "init" from my custom board init code.
What the problem? Unfortunately, it doesn't work. stdio_register returns 0 (like all OK), but "start", "tstc", "getc" were never called.
I guess I'm doing something wrong, but I cannot understand: another keyboards drivers seems to not contain any additional code for keyboard registration. Can anybody tell the truth?
Or maybe I should just hack u-boot and insert polling call somewhere in main_loop? :)
It sounds like you have created a custom device driver.
struct stdio_dev kon_dev
Try something like this at U-Boot command line to switch console to the custom driver
setenv stdin kon_dev
Of course, your custom driver will have to be debugged before you get to the happy place. It may not work the first time.
Using netconsole is similar to what you're doing. With netconsole it's possible for example to keep stdout continuously on serial device, switch stdin to nc device (that is, "setenv stdin nc", enter commands through that netcat session a while, then switch stdin back to serial.

How to read from STDIN_FILENO even if terminal is closed?

Im trying to code a program in Linux to read every input from keyboard, but using STDIN_FILENO it only reads those entered in the terminal. What I want is during execution it should read keyboard even if the terminal is closed.
STDIN_FILENO is just a helper macro.
From stdin you recieve stream of bytes that are passed to your program, they doesnt neccessary come from terminal - also can from a file, etc. It's not capturing keyboard. The terminal is capturing keyboard and then passes entered data to your program's stdin.
In order to capture keyboard you will need some other method of receiving events. I guess you are running GUI aka X server; Normally applications create windows and receive events related to them. In order to capture all keyboard events, you will have to go more low-level. Take a look at xlib which should be sufficient for you, even though it might not be.

Serial port programming - Recognize end of received data

I am writing a serial port application using VC++, in which I can open a port on a switch device, send some commands and display their output. I am running a thread which always read open port for output of given command. My main thread waits until read completes, but problem is how do I recognize that command output ends, and I should signal main thread.
Almost any serial port communication requires a protocol. Some way for the receiver to discover that a response has been received in full. A very simple one is using a unique byte or character that can never appear in the rest of the data. A linefeed is standard, used by any modem for example.
This needs to get more elaborate when you need to transfer arbitrary binary data. A common solution for that is to send the length of the response first. The receiver can then count down the received bytes to know when it is complete. This often needs to be embellished with a specific start byte value so that the receiver has some chance to re-synchronize with the transmitter. And often includes a checksum or CRC so that the receiver can detect transmission errors. Further embellishments then is to make errors recoverable with ACK/NAK responses from the receiver. You'd be then well on your way in re-inventing TCP. The RATP protocol in RFC-916 is a good example, albeit widely ignored.

Interrupt-driven driver using TTY?

I am a newbie to developing drivers for Linux ... . I am developing a SMS-driver (AT commands over serial port to modem) using TTY for accessing the serial port. The driver is written in C.
In the design messages from modem to driver can be triggered by two events:
1) Status as respond to AT commands issued by driver (i.e. expected messages)
2) Indication of new SMS (i.e. unexpected messages)
I am planning on two threads - one for writing to TTY and one for reading from TTY. Is it possible to configure TTY so that my read-thread wakes-up on incoming chars (i.e. read-thread is event-triggered and not based on polling)?
Best Regards,
Witek
I don't think you really want two threads. Typical program flow (write AT command, check response etc ...) will be easier to write and debug in a monothreaded program.
Waiting for chars can be made with select() call. The tty layer is mostly configured through
the tcsetattr, tcgetattr and friends system call. With this call you can configure wether you want to be interrupted on new line or on each char for example. See man termios for the manpage. The two big options are wether you want the special characters like EOF, EOL Ctrl-C etc... to be treated has data (raw mode) or be interpreted by the tty layer (canonical mode).
See the part on select in the serial programming guide, or the select manpage for more info

How can I monitor data on a serial port in Linux?

I'm debugging communications with a serial device, and I need to see all the data flowing both directions.
It seems like this should be easy on Linux, where the serial port is represented by a file. Is there some way that I can do a sort of "bi-directional tee", where I tell my program to connect to a pipe that copies the data to a file and also shuffles it to/from the actual serial port device?
I think I might even know how to write such a beast, but it seems non-trivial, especially to get all of the ioctls passed through for port configuration, etc.
Has anyone already built such a thing? It seems too useful (for people debugging serial device drivers) not to exist already.
strace is very useful for this. You have a visualisation of all ioctl calls, with the corresponding structure decoded. The following options seems particularly useful in your case:
-e read=set
Perform a full hexadecimal and ASCII dump of all the data read from
file descriptors listed in the
specified set. For example, to see all
input activity on file descriptors 3
and 5 use -e read=3,5. Note that this
is independent from the normal tracing
of the read(2) system call which is
controlled by the option -e
trace=read.
-e write=set
Perform a full hexadecimal and ASCII
dump of all the data written to file
descriptors listed in the specified
set. For example, to see all output
activity on file descriptors 3 and 5
use -e write=3,5. Note that this is
independent from the normal tracing of
the write(2) system call which is
controlled by the option -e
trace=write.
I have found pyserial to be quite usable, so if you're into Python it shouldn't be too hard to write such a thing.
A simple method would be to write an application which opened
the master side of a pty and the tty under test. You would then
pass your tty application the slave side of the pty as the 'tty device'.
You would have to monitor the pty attributes with tcgetattr() on the pty
master and call tcsetattr() on the real tty, if the attributes changed.
The rest would be a simple select() on both fd's copying data bi-directionally and copying it to a log.
I looked at a lot of serial sniffers. All of them are based on the idea of making a virtual serial port and sniff data from that port. However, any baud/parity/flow changes will break connection.
So, I wrote my own sniffer :). Most of the serial ports now are just USB-to-serial converters. My sniffer collects data from USB through debugfs, parse it and output to the console. Also any baudrate changes, flow control, line events, and serial errors are also recorded. The project is in the early stage of development and for now, only FTDI is supported.
http://code.google.com/p/uscmon/
Much like #MBR, I was looking into serial sniffers, but the ptys broke the parity check. However, his sniffer was not helping me, as I'm using a CP2102, and not a FT232. So I wrote my own sniffer, by following this, and now I have one that can record file I/O on arbitrary files: I called it tracie.

Resources