Sending files over Half-duplex interface - linux

I'm trying to send files over a half-duplex interface (RS-485) between a box PC running debian (4.19) and a SBC with an im6xDL.
Thanks to this community I can successfully transfer simple data between the units using picocom or by echoing/reading.
The box PC supports half-duplex RS-485 natively and has automatic RTS functions so that you can read/send data without any issue. The SBC on the other hand needs to be toggled to change into RX or TX mode.
This turned out to be a problem when I tried to send files from the box PC to the SBC.
On the box PC:
picocom /dev/ttyUSB0 -b 9600 -fn
C-a,C-S
***file: /home/user/test.txt
Transfer incomplete
*** exit status: 128
On the SBC
picocom /dev/ttymxc2 -b 9600 -fn -et
C-a,C-r
Terminal ready
�000000
As you can see something is terribly wrong, it is like it cannot interpret the bits when a file is being transferred.
My questions:
Is it possible to send files from the command line in half-duplex systems? (The SBC needs to be in RX mode the entire time).
Is there another way to achieve this that is more intuitive?
As always, thanks for the help and support :)
/W

See here:
Pymodbus - Read input register of Energy meter over rs485 on uart of raspberry pi3
The solution I presented there using pylibmodbus should work for any hardware with UART and one or two GPIO lines accessible from user space in Linux.
If, on the other hand, what you want to do is use something like picocom or minicom then you can take a look at the hardware-only solution using a 555 timer.
Of course, if prototyping circuits is not for you, you can always buy a USB to RS485 with half-duplex support. You have many available but those based on the MAX13487 IC seem to work very well.
EDIT: The solution using the 555 timer is not in the post I linked above but here together with some more background material on half-duplex RS485 links: RS485: Inappropriate ioctl for device

Related

Socat pseudo terminal: Can you make use of data lines (DTR, RTS etc)?

I'm creating a virtual serial port using socat.
socat -d -d pty,echo=0,raw pty,echo=0,raw
That works as expected so far. Using echo/cat I can send/receice text etc.
But what about signal lines like DTR or RTS? How would I get / set the state of these lines with a pty? Is that even possible? I couldn't find any mentions about it anywhere.
socat is a pipe handler, basically lets you tap in the Tx and Rx "lines" without you having to care about signaling when data is ready/received.
The RTS/CTS/DSR/DTR are actual pins in a serial connector that control what is going on on the Tx/Rx lines.
Off the top of my head, I haven't used socat nor tried to do anything similar, lowest possible level I got was the EMV interface and protocol and sometimes I also netcat stuff real quick between machines when I'm too lazy to cp to a directory within httpd home... anyway, if you are trying to connect two entities with socat (separate machines, or applications on the same machine) you'll either use the same pipe and specify some control characters so they end up talking at the same time (got to make a note of this and try to implement it somehow with my wife), or use two separate pipes, one for Rx and one for Tx: Tx of entity 1 goes into Rx of entity 2, Tx of entity 2 goes into Rx of entity 1.
From your comment, it sounds like you want to control RTS/CTS independent of your data stream. You will have to write an application to interact with the serial port using ioctls.
I found this helpful forum post (with an example application)
https://www.linuxquestions.org/questions/programming-9/manually-controlling-rts-cts-326590/
You can use hardware flow control lines (RTS/CTS):
socat stdio file:/dev/ttyAMA0,crtscts=1,b9600
Nowadays, this is mostly useful when talking to an RS485 transceiver, since that's the most common example of half-duplex serial line that is still in use. On some commonly used transceivers, such as the 75HVD12, the DE (drive enable) pin is connected to the host's RTS. There's also an active-low /RE (receive enable) pin that is connected to either RTS or CTS.
If you have access to GPIO, such as on a Raspberry Pi, you might be able to assign DTR and DSR to an output and input pin respectively. Alternatively, an USB adapter such as FTDI232 will assert DTR if it is connected to a computer.

USB-Serial communication giving strange output

I'm trying to get data from a mercury analyzer (Seefelder-Messtechnik Hg Analyzer 3000) that gives output to a 9-pin R232 serial port to my OSX 10.10 laptop.
I've followed the steps described here to install the PL-2303 driver:
http://pbxbook.com/other/mac-tty.html
The device manual (http://www.seefelder-messtechnik.com/V71-3-02-21e.pdf) lists the communication protocol as "9600 Baud, 8 data bit, 1 stop bit, no log,
no parities".
I attempt to read from the device by using the 'screen' command:
screen /dev/tty.usbserial 9600
The result is a string of seemingly non-sensical characters that print to the screen in a regular interval:
�8b4����b��8b48bs��8G�8b�8���8������8����< 8�8��b��KW��\b����8b����b� �b�b����KW�K �8b��\G�� �<���8�8b�"��΁�[؁��؉���bG�3�ˁ�G��\K��[W�pb�8��΁8ʱ�\pa���ʁ�c t��8�h¡�38b�8�q�؁����\�8���bS�8b8�8�q���X��8��<��£8���2�8�����ؖ�ؖ�ؖ�8bS��\�܉�ؖ����[S�8��s���fq�8�����������8fq����������S�܊��b���b�؉����\���S��K���ݎ����S��b��b��S����S�\������KS��S�؊��\S�1S�\b�S�؉�\�ذ����KS�\����S����bS�؉�����1S�؊��[؂����ز������؉\�؂��ز��\����i���$\�$���\��8���$��\�\����܂�زXk�B��7��\k�\X�<��8Xkz��Yj��L�������H�\���]j�،k:��Yj�؈��
I've also tried using 'minicom' rather than screen, and get a different ("?]???ܰ??Yk??2"), but also non-sensical result. I saw that there was another SO query similar to mine that remains unsolved: weird characters displayed during serial communication OSX
Any tips? It looks to me that I'm not interpreting the output correctly, but I don't know what to try next.
The solution was to read from the machine at a higher baud rate (~57600), despite what the manual and online reference said. Reading at 57600 baud made the result plain-text and usable. Thanks for your ideas!
I've followed the steps described here to install the PL-2303 driver
I've also had occasional electrical ground problems with Prolific USB-RS232 adapters. Problem would manifest as garbled data that looked similar to a baud rate issue or what you posted.
You can check if it's a ground issue by measuring for continuity between the ground pin (pin #5) on the DE-9 (aka DB-9) side of the Prolific adapter and the ground pin of the USB side (pin #4, "far left", of the A connector). You'll probably measure infinite resistance with a multimeter. Try the same with a FTDI USB-RS232 adapter, and instead I get a dead short between the ground pins as expected.
Be sure to plug the instrument's and PC's power supplies into the same power strip.
As a last resort try grounding the instrument's chassis/case with the PC using copper wire

Bi-directional sniffing/snooping on an ALSA MIDI SysEx exchange

Does anyone know of a good way to get a bi-directional dump of MIDI SysEx data on Linux? (between a Yamaha PSR-E413 MIDI keyboard and a copy of the Yamaha MusicSoft Downloader running in Wine)
I'd like to reverse-engineer the protocol used to copy MIDI files to and from my keyboard's internal memory and, to do that, I need to do some recording of valid exchanges between the two.
The utility does work in Wine (with a little nudging) but I don't want to have to rely on a cheap, un-scriptable app in Wine when I could be using a FUSE filesystem.
Here's the current state of things:
My keyboard connects to my PC via a built-in USB-MIDI bridge. USB dumpers/snoopers are a possibility, but I'd prefer to avoid them if possible. I don't want to have to decode yet another layer of protocol encoding before I even get started.
I run only Linux. However, if there really is no other option than a Windows-based dumper/snooper, I can try getting the USB 1.1 pass-through working on my WinXP VirtualBox VM.
I run bare ALSA for my audio system with dmix for waveform audio mixing.
If a sound server is necessary, I'm willing to experiment with JACK.
No PulseAudio please. It took long enough to excise it from my system.
If the process involves ALSA MIDI routing:
a virtual pass-through device I can select from inside the Downloader is preferred because it often only appears in an ALSA patch bay GUI like patchage an instant before it starts communicating with the keyboard.
Neither KMIDIMon nor GMIDIMonitor support snooping bi-directionally as far as I can tell.
virmidi isn't relevant and I haven't managed to get snd-seq-dummy working.
I I suppose I could patch ALSA to get dumps if I really must, but it's really an option of last resort.
The vast majority of my programming experience is in Python, PHP, Javascript, and shell script.
I have almost no experience programming in C.
I've never even seen a glimpse of kernel-mode code.
I'd prefer to keep my system stable and my uptime high.
This question has been unanswered for some time and while I do not have an exact answer to your problem I maybe have something that can push you in the right direction (or maybe others with similar problems).
I had a similar albeit less complex problem when I wanted to sniff the data used to set and read presets on an Akai LPK25 MIDI keyboard. Similar to your setup the software to setup the keyboard can run in Wine but I also had no luck in finding a sniffer setup for Linux.
For the lack of an existing solution I rolled my own using ALSA MIDI routing over virmidi ports. I understand why you see them as useless because without additional software they cannot help at sniffing MIDI traffic.
My solution was programming a MIDI relay/bridge in Java where I read input from a virmidi port, display the data and send it further to the keyboard. The answer from the keyboard (if any) is also read, displayed and finally transmitted back to the virmidi port. The application in Wine can be setup to use the virmidi port for communication and in theory this process is completely transparent (except for potential latency issues). The application is written in a generic way and not hardcoded to my problem.
I was only dealing with SysEx messages of about 20 bytes length so I am not sure how well the software works for sniffing the transfer of large amounts of data. But maybe you can modify it / write your own program following the example.
Sources available here: https://github.com/hiben/MIDISpy
(Java 1.6, ant build file included, source is under BSD license)
I like using aseqdump for that.
http://www.linuxcommand.org/man_pages/aseqdump1.html
You could use virtual midi devices for this purpose. So you have to load snd_seq_dummy so that it creates at least two ports:
$ sudo modprobe -r snd_seq_dummy
$ sudo modprobe snd_seq_dummy ports=1 duplex=1
Then you should have a device named Midi through:
$ aconnect -i -o -l
client 0: 'System' [type=kernel]
0 'Timer '
1 'Announce '
client 14: 'Midi Through' [type=kernel]
0 'Midi Through Port-0:A'
1 'Midi Through Port-0:B'
client 131: 'VMPK Input' [type=user,pid=50369]
0 'in '
client 132: 'VMPK Output' [type=user,pid=50369]
0 'out '
I will take the port and device numbers form this example. You have to inspect them yourself according to your setup.
Now you plug your favourate MIDI Device to the Midi Through ports:
$ aconnect 132:0 14:0
$ aconnect 14:0 131:0
At this time you have a connection where you can spy on both devices at the same time. You could use aseqdump to spy the MIDI conversation. There are different possibilities. I suggest to spy the connection between the loopback devices and the real device. This allows you for rawmidi connections to the loopback devices.
$ aseqdump -p 14:0,132:0 | tee dump.log
Now everything is set up for use. You just have to be careful about port names in your MIDI application. It should read MIDI data from Midi Through Port-0:B and write data to Midi Through Port-0:B.
Some additional hint: You could use the graphical frontend patchage for connecting and inspecting the MIDI connections via drag and drop. If you do this you will see that every Midi Through port occurs twice once as input and once as output. Both have to be connected in order to make this setup work.
If you want to use GMidiMonitor or some other application you spy on both streams intermixed (without showing the direction) using aconnect suppose 129:0 is the Midi Monitor port :
$ aconnect 14:0 129:0
$ aconnect 132:0 129:0
If you want to have exact direction information you could add another GMidiMonitor instance that you connect only to one of the ports. The missing messages come from the other port.
What about using gmidimonitor? See http://home.gna.org/gmidimonitor/

PCM voice data on serial port to sound device conversion in linux

I have a telephony modem which gives voice to my interfaced application via a serial USB ttyUSB0 in 16bit PCM 8000hz. I am able to capture this data and play with audacity. I want this port to be detected as a sound device in linux (I am on ubuntu). Is it possible? Are there any other options?
I'm guessing you are using a huawei 3G modem or something similar which gives ttyUSB1 for audio. Make sure you have the serial driver binded to it. Then simply pass the port itself as a "file" for input for any program of your choice.You need root access for that.You figured out the audio settings so it must be enough.I have voice calling working in UBUNTU 11.10 with Huawei. So let me know if i can help any further.
Ok, I see it's very old question but answers helped me to get a right direction so I decided to help others.
The one way to achieve (in addition to below) what are you are
looking for is to write dynamic kernel module.
Have it register as a sound device, and check that it has a GSM
module present (which module is it exactly can be recognized in
dmesg, lsmod, or output).
Then establish communication between user space representation as a
sound card and serial usb module.
The other way is to get module that you recognized by dmesg, lsmod and extend its functionality as a sound card.
All are tricky tasks because:
in the first case you have to resolve intermodule communication at the kernel level...... which is, lets say, a little hard even if programmer has a right background in subject.
the second case is hard in that you have to deal with:
USB stack (which is little unpleasant for human beings) and
sound subsystem (which is a little burdensome because of historical issues).
Without being an experienced kernel programmer there are small chances to succeed.

Controlling a USB power supply (on/off) with Linux

Is it possible to turn on/off power supplies from USB manually with Linux?
There's this external USB cooling fan (the kind you use to cool yourself off, not the PC), and it would be nice to be able to control it from the terminal, because I want to position the fan somewhere far away.
I suppose this could also be useful for a variety of other things as well, because there's a lot of USB toys out there. Maybe air purifiers, etc. (I heard they don't really work though).
According to the docs, there were several changes to the USB power management from kernels 2.6.32, which seem to settle in 2.6.38. Now you'll need to wait for the device to become idle, which is governed by the particular device driver. The driver needs to support it, otherwise the device will never reach this state. Unluckily, now the user has no chance to force this. However, if you're lucky and your device can become idle, then to turn this off you need to:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend"
echo "auto" > "/sys/bus/usb/devices/usbX/power/level"
or, for kernels around 2.6.38 and above:
echo "0" > "/sys/bus/usb/devices/usbX/power/autosuspend_delay_ms"
echo "auto" > "/sys/bus/usb/devices/usbX/power/control"
This literally means, go suspend at the moment the device becomes idle.
So unless your fan is something "intelligent" that can be seen as a device and controlled by a driver, you probably won't have much luck on current kernels.
Note. The information in this answer is relevant for the older kernels (up to 2.6.32). See tlwhitec's answer for the information on the newer kernels.
# disable external wake-up; do this only once
echo disabled > /sys/bus/usb/devices/usb1/power/wakeup
echo on > /sys/bus/usb/devices/usb1/power/level # turn on
echo suspend > /sys/bus/usb/devices/usb1/power/level # turn off
(You may need to change usb1 to usb n)
Source: Documentation/usb/power-management.txt.gz
PowerTOP from Intel allows you to toggle devices such as usb peripherals in real-time. These are called 'tunables'.
sudo apt install powertop
sudo powertop
Tab over to 'tunables'.
Scroll down to your device.
Hit enter to toggle power saving mode (Good/Bad)
Note that Bad means the device is always on. Toggling to Good will turn off the device after the preset inactive saving time (default is 2000ms).
See the PowerTOP docs for details on how to make these changes permanent.It generates the config scripts for you (pretty much as described by other posters on this thread).
NOTE: These scripts do not affect USB pin power (which is always on).
These only send the driver protocol to activate and deactivate a device.
If you want to control pin power, you could use either a supported smart USB hub, or better yet a microcontroller.
I have found these solutions that at least work for properly configured Terminus FE 1.1 USB hub chip:
1.To turn off power on all USB ports of a hub, you may unbind the hub from kernel using:
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/unbind
to turn power back on - you may bind it back using
echo "1-4.4.4" > /sys/bus/usb/drivers/usb/bind
2.Switching power at each port individually is trickier: I was able to use hubpower to control each port - but it comes with a downside: hubpower first disconnects the usbdevfs wich causes all of the USB devices to disconect from system, at least on ubuntu:
usb_ioctl.ioctl_code = USBDEVFS_DISCONNECT;
rc = ioctl(fd, USBDEVFS_IOCTL, &usb_ioctl);
With this ioctl disabled I was able to switch off individual port power without detaching all devices - but the power goes back on immediately (probably due to kernel seeing an uninitialized device) which causes USB device just to do a "cold restart" which is what I generally wanted to do. My patched hubpower is here
You could use my tool uhubctl to control USB power per port for compatible USB hubs.
I wanted to do this, and with my USB hardware I couldn't. I wrote a hacky way how to do it here:
http://pintant.cat/2012/05/12/power-off-usb-device/ .
In a short way: I used a USB relay to open/close the VCC of another USB cable...
echo '2-1' |sudo tee /sys/bus/usb/drivers/usb/unbind
works for ubuntu
The reason why folks post questions such as this is due to the dreaded- indeed "EVIL"- USB Auto-Suspend "feature".
Auto suspend winds-down the power to an "idle" USB device and unless the device's driver supports this feature correctly, the device can become uncontactable. So powering a USB port on/off is a symptom of the problem, not the problem in itself.
I'll show you how to GLOBALLY disable auto-suspend, negating the need to manually toggle the USB ports on & off:
Short Answer:
You do NOT need to edit "autosuspend_delay_ms" individually: USB autosuspend can be disabled globally and PERSISTENTLY using the following commands:
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="/&usbcore.autosuspend=-1 /' /etc/default/grub
update-grub
systemctl reboot
An Ubuntu 18.04 screen-grab follows at the end of the "Long Answer" illustrating how my results were achieved.
Long Answer:
It's true that the USB Power Management Kernel Documentation states autosuspend is to be deprecated and in in its' place "autosuspend_delay_ms" used to disable USB autosuspend:
"In 2.6.38 the "autosuspend" file will be deprecated
and replaced by the "autosuspend_delay_ms" file."
HOWEVER my testing reveals that setting usbcore.autosuspend=-1 in /etc/default/grub as below can be used as a GLOBAL toggle for USB autosuspend functionality- you do NOT need to edit individual "autosuspend_delay_ms" files.
The same document linked above states a value of "0" is ENABLED and a negative value is DISABLED:
power/autosuspend_delay_ms
<snip> 0 means to autosuspend
as soon as the device becomes idle, and negative
values mean never to autosuspend. You can write a
number to the file to change the autosuspend
idle-delay time.
In the annotated Ubuntu 18.04 screen-grab below illustrating how my results were achieved (and reproducible), please remark the default is "0" (enabled) in autosuspend_delay_ms.
Then note that after ONLY setting usbcore.autosuspend=-1 in Grub, these values are now negative (disabled) after reboot. This will save me the bother of editing individual values and can now script disabling USB autosuspend.
Hope this makes disabling USB autosuspend a little easier and more scriptable-
I had a problem when connecting my android phone, I couldn't charge my phone because the power switch on and then off ...
PowerTop let me find this setting and was useful to fix the issue ( auto value was causing issue):
echo 'on' | sudo tee /sys/bus/usb/devices/1-1/power/control
USB 5v power is always on (even when the computer is turned off, on some computers and on some ports.) You will probably need to program an Arduino with some sort of switch, and control it via Serial library from USB plugged in to the computer.
In other words, a combination of this switch tutorial and this tutorial on communicating via Serial libary to Arduino plugged in via USB.
So far I came to the conclusion that you cannot control the power of a USB port. The 5V USB is always provided, and it's up to the device to use it or not. You can check this with a 5V fan or light.
I've tried various methods (disconnect/reconnect/bind/unbind/reset signal). Best so far are bind/unbind as it forces a cold restart of the device (but no power cycle).
I came up with a solution to reset USB devices, ports and controllers in a python script, which supports all of the above methods.
You can find the script at my Github page
Usage:
usb_reset.py -d 8086:1001 --reset-hub
The script uses among others the following solution to reset USB hubs/controllers:
Unbindind a USB port / controller works best via:
echo "myhub" > "/sys/bus/usb/drivers/usb/unbind"
echo "myhub" > "/sys/bus/usb/drivers/usb/bind"
Where myhub is found in /sys/bus/usb/devices/*
Or litteral controllers:
echo "mycontroller" > "/sys/bus/pci/drivers/unbind"
echo "mycontroller" > "/sys/bus/pci/drivers/bind"
Where mycontroller is found in /sys/bus/pci/drivers/[uoex]hci_hcd/*:*

Resources