How to open serial port in linux without changing any pin? - linux

Posix requires changing RTS pin on port opening. I want a way to avoid it.

I have no idea why you'd want to do this, but this can be done pretty easily by modifying the linux kernel driver for your serial console so it doesn't toggle RTS. For example, for the 8250-series driver in drivers/tty/serial/8250/ you could change every write to the MCR register (UART_MCR) to ensure that bit 1 (mask is UART_MCR_RTS) is never set.
Since it's abstracted away in userspace, you're out of luck if you want to do this without modifying the kernel driver.

Having the same problem, I'd give it a try by patching the ftdi_sio kernel driver. You just need to uncomment a small piece of code in ftdi_dtr_rts() like this:
static void ftdi_dtr_rts(struct usb_serial_port *port, int on) {
...
/* drop RTS and DTR */
if (on)
set_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- HERE
else
clear_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- and HERE
}
and the RTS handshake line is not longer changed upon open() call.
Note, that the uart than might not longer working with RTS/CTS hardware handshake, as long as your modified kernel driver is loaded. But you can still control the state of the RTS handshake line manually by calling e.g.:
int opins = TIOCM_RTS;
ioctl(tty_fd, TIOCMBIC, &opins);
I'd tested this with the Ctrl+A+G command of picocom 2.3a, running Kubuntu 16.04 64 bit and Ftdi FT2232H based usb uart adapter.
You might find more details on this topic here.

A change in the DTR pin can be (eventually) avoided using the command line
stty -F /dev/ttyUSB0 -hupcl
This has the effect of making DTR turn on; and subsequently when the port is opened and closed, DTR is not affected.
Source: https://raspberrypi.stackexchange.com/questions/9695/disable-dtr-on-ttyusb0/27706#27706
And there is code there to do the same thing from python via termios, this can be done before opening the port via pyserial:
import termios
path = '/dev/ttyACM0'
# Disable reset after hangup
with open(path) as f:
attrs = termios.tcgetattr(f)
attrs[2] = attrs[2] & ~termios.HUPCL
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
The OP was running this on a Raspberry Pi, but I just tried it on Linux Mint on x86_64, it worked. I don't know how RTS is affected.
The reason I find this useful, is for communication with an Arduino Nano - which has a USB-> serial chip on board - and normally the Arduino gets reset every time you open the serial port from linux (rising edge of DTR causes reset). For some applications, this is not a problem, but it's clearly useful to avoid this for other applications, and it's not so easy to remove that tiny capacitor from the Arduino which connects DTR to reset.
You will still get a single reset when the stty command is executed (after plugging in the USB cable). But at least you can then keep opening and closing the serial port after that without further resets.

calling fopen("/dev/ACM0", "r") doesn't require you do do anything:) You may not receive the data you expect though.

Related

Sending files over Half-duplex interface

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

How can I blink LEDs in a Linux kernel module?

I have a laptop with Linux Mint and 4.4.0-78-generic kernel.
Also, I have some LEDs there in the /sys/class/leds directory, and I can turn them on and off in the userspace by executing "echo 255 > brightness" in Bash.
However, I want to switch them in my kernel module. Let’s say, that this module will listen a UDP socket and switch LED based on incoming packet data.
I have googled and found kernel source files called "leds-base.c", "leds-class.c" which contains functions to control LEDs. However, this functions require "struct led_classdev" to be passed, and I don't know where do I should get it.
How can I set LED brightness using its name from /sys/class/leds directory in a kernel module?
PS. I have seen a similar question, but it's about keyboard LEDs only, the LED I want to control is not a keyboard one, and can not be controlled by code in question mentioned before.
Implement an led_trigger class and call
led_trigger_event(led, LED_FULL);
and friends in your driver. You can bind your trigger to any LED by
echo my-trigger-name > /sys/class/leds/.../trigger

Linux: calling open() on a USB device which may not be present

I have a device attached to a Raspberry Pi. The Pi is running ARCH Linux. The device communicates with the Pi via USB. The device has to be switched on and off via a pulse and I have control, from the Pi, of a relay which causes this pulse. However I can never be sure whether the device is initially on or off.
In my code I toggle the relay and then speculatively call open() on the device (with flags O_RDWR | O_NOCTTY). The problem is that if I am doing this when the device is off the open() call hangs. I have tried waiting for 1 second after the toggle, for things to settle, but that hasn't helped. I have tried calling stat() before the open() call but this always returns zero (so the device is there as far as stat() is concerned). I have tried specifying O_NON_BLOCK in the open() call but that causes it to always fail.
Can anyone suggest either (a) what I'm doing wrong or (b) a reliable way forward?
You can be certain that the device has powered if it has USB enumerated. You can use libudev to find the list of USB enumerated devices and check whether your device is on that list.
The command line "lsusb" does that. So if you need an example of how to use libudev then you can read the lsusb source code (https://github.com/gregkh/lsusb).
If you can be sure that the device will eventually turn up, the blocking open() ("hangs") may actually be what you want! The call to open() will return, hopefully with success, when your device turns up.
The stat() call simply checks if the device special file is there. It can't tell you if there is anything listening.
One possible way forward, would be to open() with O_NONBLOCK in an exponential back-off loop.
Depending on what you mean with "communicates via USB", you may want to use libusb. If it's just a USB serial port, wrapping open() yourself is probably the easiest though.
It's not clear what you have done to get a device file that survives disconnect.
The usual approach is to use hotplug+udev to create (and remove) the device symlinks, then the special file would only be there when the device is plugged in.
Courtesy of all the helpful people below, the quick answer was to include in my .rules file a "remove" action to go with the existing "add" action. So in the file where I have:
ACTION=="add", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK+="OrangutanUSB"
...to give me a /dev/OrangutanUSB device, I have included a new line:
ACTION=="remove", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK-="OrangutanUSB"
...to cause the operating system to remove the /dev/OrangutanUSB device when it has been powered off. This way the open() call fails correctly when the device has gone, rather than hanging.
Ultimately, what I should do is check that the device is enumerated, rather than expecting open() to fail, but that can wait until I have the time. For now my code works as originally intended.

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/*:*

How do I read events from a HID device under Ubuntu Jaunty?

I have a Linux USB HID device (a Hama MCE), and I can read its events manually by reading cat /dev/input/event7 and cat /dev/input/event8. Whenever I press a key on the device, a few bytes become available for reading with one of the cat commands above. I have a default installation of Ubuntu Jaunty 64-bit desktop on the machine.
I think I can write a parser to interpret the bytes emitted by the device, or I'll use libhid if it's more convenient.
My questions are:
How do I prevent the text-mode virtual consoles from receiving some of the key presses on the device as normal keypresses? As of now, some device keys result an Enter, a BackSpace, a PageUp or numeric keypad numbers.
Similarly, how do I prevent the X server from receiving keyboard and mouse events from this device? I have several USB keyboards and mice connected to the computer. I want the X server receive events from all of them, except for this device.
How do I set up that whenever the device gets connected to the computer, the command /usr/local/bin/keydumper /dev/input/event7 /dev/input/event8 (or one command for each /dev/ path) would get run, with the proper /dev/ paths substituted in the command line?
Answering my own question based on answers from the Linux USB HID driver developers:
Question 1. and 2.: Do
ioctl(open("/dev/input/event7", O_RDONLY), EVIOCGRAB, 1);
As long as this filehandle is open, the events generated would go only
to this filehandle (not to other open()s of the same device or to the
system keyboard or mouse event pool). At most one process can hold a
successful EVIOCGRAB at a HID device at a time. Lirc can be configured
to do an EVIOCGRAB.
Question 3.: Configure udev to start the program once the device is connected.
I do not have enough points to comment sadly.
If you are looking for the definition of EVIOCGRAB try
#include <linux/input.h>
I think solution for all questions can be writing own filter device driver, or custom driver for your device. I know such a thing (filter device driver) is available on windows so something similar can be on Linux. In that filter device driver you could block all unwanted events from the target device that you wish to block, I don't really get 3 question so I don't know how to answer for that.

Resources