how to duplicate /dev/ttyUSB0 stream? - linux

Is there a way to duplicate a serial device /dev/ttyUSB0 on Linux (Ubuntu 14.04) ?
I made a program which read the data from the RS232 port and I would like to execute two instances of my program with different options in parallel. However, I cannot open the /dev/ttyUSB0 twice from my program (writen in C).
Ideally, I would like the ttyUSB0 driver to create two identical devices. (/dev/ttyUSB0 and /dev/ttyUSB1). The driver would make sure that ttyUSB1 is an exact copy of ttyUSB0.
Is there a way to perform this from the command line (bash) or should I make my own special serial port driver ?

You can use tee to output anything written to /dev/ttyUSB0 to two named pipes.
mkfifo copy1 copy2
tee copy1 copy2 < /dev/ttyUSB0 > /dev/null &
program1 < copy1
program2 < copy2
(Strictly speaking, you only need one named pipe; the other program could read from an anonymous pipe connected directly to tee. This symmetrical treatment is a little cleaner, though.)

Related

Loopback/Echo bytes received over serial port

On an embedded Linux system running Busybox I am trying to receive bytes over a serial port and echo back everything received.
The system setup is like this:
Linux <-USB-> FTDI chip <-UART-> MCU
On the UART line I have a logic analyser monitoring the data between the FTCI chip and the MCU. Both the MCU and Linux have the same UART configuration.
The script I have written runs on the Linux system and is supposed to send back all data it received from the MCU.
So far I have this simple Bash script which is to receive bursts of data 62 bytes long. The timeout is set to 5 seconds as a sort of alive signal.
#!/bin/bash
# Enable debugging
set -x
# Set the baudrate of the port
stty -F /dev/ttyUSB0 1500000
while true
do
# Read 62 bytes with a timout of 5 seconds to variable RESP.
read -N62 -t5 RESP < /dev/ttyUSB0
# Print out how many bytes we received
echo ${#RESP}
# Send back the data, -n for no trailing new line
echo -n $RESP > /dev/ttyUSB0
done
There are a few problems I have with this script:
Not all bytes are received consistently. I've been testing now for some time an only seen the full number of bytes once.
It outputs only 0xFF values on the UART bus, this is observed through the logic analyser.
What am I missing here in order to receiving the correct data and send it back correctly?
Through the suggestions made by #sawdust I was able to get a working script.
In the end I stopped using the read command. I was unable to get it to work in raw mode. I could not use termios as this in to available on my Busybox system. I got a working setup using dd:
#!/bin/bash
stty -F /dev/ttyUSB0 raw
stty -F /dev/ttyUSB0 1500000
dd if=/dev/ttyUSB0 count=62 of=/dev/ttyUSB0

Creating a bash script that logs the output of 'watch lsusb' into an empty file

I have an embedded Linux system (running Ubuntu 10) on a microprocessor that has an onboard USB hub (specifically a BeagleBone Black).
I made a simple bash script that's supposed to run a command, watch lsusb; and as that runs, my program needs to dump the output my command generates into a text or JSON file (ideally on a USB stick, called usb0 for the sake of the example).
So far, this is what I have:
#!/bin/bash
#DATE=$(date +'%F %H:%M:%S')
DIR=/home/ubuntu/lsusb_logs
CMD='watch lsusb'
$CMD > $DIR
This runs until I stop it, which is fine. But when I go to look at my now created lsusb_logs file, all the data appears to be either encoded or needs to be formatted because its not at all like the original format a single lsusb or even watch lsusb outputs.
The purpose of this script is to gather historical data of the peripherals on the USB hub state over a 24 hour period in an environment chamber (climate stress testing).
Any advice or insight is helpful, thanks.
watch is going to print some non-readable characters because it needs to clear the screen every time it runs the command. You could however just run the command in an infinite while loop with some delay:
while true; do
lsusb >> lsusb_logs
sleep 1 # 1 second delay
done
Instead of looping through the same repetitive command indefinitely, you can take another approach.
You can utilize udev to monitor for plugged or unplugged USB devices, and execute a script at that time.
Example, create 2 scripts:
vi /bin/device_added.sh
vi /bin/device_removed.sh
which will log to a log file the ACTION (added or removed),
and make those executable:
chmod +x /bin/device_added.sh
chmod +x /bin/device_removed.sh
then create a udev rule that will contain the triggers on when a device change is detected:
vi /etc/udev/rules.d/80-test.rules
which will contain for example:
SUBSYSTEM=="usb", ACTION=="add", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_added.sh"
SUBSYSTEM=="usb", ACTION=="remove", ENV{DEVTYPE}=="usb_device", RUN+="/bin/device_removed.sh"
This way with your 2 scripts log only upon change, and not all the time..

Reading from a USB device using bash and raspberry pi 3?

I'm trying to catch the response from a device that is connected to the USB.
With this code:
sudo stty -F /dev/ttyUSB0 speed 115200 cs8 -cstopb -parenb -echo
sudo stty raw; cat > /home/received.log < /dev/ttyUSB0
echo "Monitor started"
On port ready, send the command request to the device
echo -en '\x5A\x00\x00\x0D\x0A\x71' > /dev/ttyUSB0
then read the log and paste the response in another file converting it properly
xxd -plain /home/received.log > /home/output.txt
so I can show the data,
cat -v < /home/output.txt
But I'm needing something more stable, that code is showing me this error:
stty: 'standard input': Inappropriate ioctl for device
which is weird, because it was working...
I would like to catch the response and store it in a variable.
i suggest getting rid of the stty raw.
Unless you are sending/receiving special characters that the tty subsystem will process, which is unlikely - because you said it is working - you almost certainly won't need it.
If it did work, you might find some undesirable side effects such as:
backspace does not erase a character that you miss-typed
control-c won't terminate your process
and other things that you might rely on in your terminal session.
FWIW, i am doing a similar thing with Arduino to Mac, Windows (cygwin) & Linux (read from the usb/serial port) and i have not been tempted to stty raw in any of those environments.

Read raw USB data for port being used by VirtualBox

I have software for communicating with a serial device that only runs on Windows 7. My host machine is running Ubuntu 16.04, with Windows 7 in virtual box.
I've managed to set it up using USB device filters in VirtualBox settings so that Windows sees and can communicate with the device.
However I'd like to capture what's being sent to and from the device. I thought something as simple as cat /dev/ttyUSB0 would work but unfortunately when I start VirtualBox I get this in dmesg:
[31199.465270] vboxdrv: ffffffffc0df4020 VMMR0.r0
[31199.653494] vboxdrv: ffffffffc0ef7020 VBoxDDR0.r0
[31199.710573] VBoxNetFlt: attached to 'wlp1s0' / 98:54:1b:04:13:48
[31199.863579] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[31199.863674] ftdi_sio 1-3:1.0: device disconnected
So I don't know which file to monitor in /dev anymore. I suppose I might be able to try listen for the communication from Windows, but if I can I'd like to know if it's possible to monitor it from my host machine.
Edit:
This answer helped me for a start. I now get some cool looking stream on the terminal, next step is deciphering it, or if anyone has a better way I'm interested - it looks like the person who answered that question still has deciphering it as a TODO :-)
The fact that it was communicating with software in VirtualBox didn't really matter. This answer got me most of the way just by (as root):
modprobe usbmon
cat /sys/kernel/debug/usb/devices|less and search for device
cat /sys/kernel/debug/usb/usbmon/7u where 7 is the number from "Bus=" in the device table from step 2
From there is was just filtering the output.
A basic way could be just
cat /sys/kernel/debug/usb/usbmon/1u |cut -d\ -f9- | grep ^\n
But the device I was working with was constantly sending lines with just 4 characters, to filter out those I got the address word from the output line, and grepped for that. In my case I only wanted to capture "C" or callback output. I was also filtering for lines that contained more than just the default "0160" that the device was constantly outputting. To try understand the hex output I put a xxd -r -p at the end which gave me:
cat /sys/kernel/debug/usb/usbmon/1u | grep -e 'C Bi:1:005:1\s0\s\w*\s=\s0160\w' | cut -d\ -f8- | xxd -r
Where the grep is
grep -e 'C <address> <someotherstuff> = <always-output-string><anycharacter>
This still gave me this indecipherable junk below, but I don't know the format so I'm stuck here. Maybe the steps to read and filter will be useful for someone
>
O�UDQN��RG_JAMS142E DEFAULT0XXXXXXX�lSTz:�RSDU�vy��������������������������z�fff=�����{6zC"z�u6zC�z�H
;�����C��Af[���RSC�b ISD�EGIN
�CG_IEW0321:0407JUN12S��Z-�$''$'''C'''

Using gnu screen to access serial port

I am trying to access a device which is attached to a USB-serial port. The settings are 57600 baud, 8 bit, 1 stop bit, no parity. The device outputs a status line every second and accepts typed commands.
I would like to use GNU screen to initiate 2 way communications, so I am using this command:
screen /dev/ttyS2 57600,cs8
However I just get a blank screen, nothing received from the device.
The communication is fine using teraterm, and I can also do this
stty -F /dev/ttyS2 57600 cs8
cat /dev/ttyS2
to see the status output from the device.
I've tried various combinations of ixon, ixoff, crtscts, and clocal but nothing makes any difference.
How can I determine what the correct command should be?
I am using Cygwin on Windows 10.
I faced the same issue with gnu-screen, I started using plink.exe instead from the PuTTY suite. It's not optimal, but it does the job. In my case serial is just for recovery, not for everyday usage.
Start PuTTY, create a profile with your serial connection.
Name and save the connection.
From cygwin, run: '/cygdrive/c/Program\ Files\ (x86)/PuTTY/plink.exe -load SerialProfile'

Resources