DeskPi-Team / deskpi

DeskPi Pro is the Ultimate Case Kit for Raspberry Pi 4 with Full Size HDMI/2.5 Hard Disk Support and Safe Power Button, It has QC 3.0 Power Supply inside and New ICE Tower Cooler inside.
GNU General Public License v3.0
143 stars 46 forks source link

Use of hard-coded /dev/ttyUSB0 in fan drivers can cause conflict #118

Open iainaff opened 2 years ago

iainaff commented 2 years ago

Problem

The code for the fan drivers, etc, uses a hard-coded device - /dev/ttyUSB0

This is very bad practice, and will cause failures if other USB serial devices are present at boot & device enumeration.

Because the fan serial device is on the USB-C bus - bus 3, device 3 - it will fall to be enumerated AFTER any other USB serial devices present, so will not be numbered as /dev/ttyUSB0, as the devices(s) on the lower buses will get that, so the drivers using the hard-coded /dev/ttyUSB0 device name will open the wrong device , thus breaking both the fan control and the other serial device.

Fix

The simplest fix for this is to use udev rules to cause creation of a symlink to the dynamically assigned /dev/ttyUSB?, and then use that instead of the hard-coded /dev/ttyUSB0.

To get udev to do this, a file /etc/udev/rules.d/20-serial.rules is created, containing:

SUBSYSTEM=="tty",ATTRS{idVendor}=="1a86",ATTRS{idProduct}=="7523",SYMLINK+="ttyFAN0"

(Note than this is a the simplest possible rule; if any other devices of the same vendor:product ID are also present, it will have to be more specific, eg identifying the bus & device, etc, to uniquely identify it, and prevent the same conflict problem happening).

This rule creates a device symlink /dev/ttyFAN0 (pointing to the dynamically assigned /dev/ttyUSB?) which the fan drivers can then safely open and use.

Other necessary changes to the C and Python code from the drivers directory are below, as a git diff:

Patch

diff --git a/drivers/c/fanStop b/drivers/c/fanStop
index f0b09f9..ff18723 100644
--- a/drivers/c/fanStop.c
+++ b/drivers/c/fanStop.c
@@ -10,9 +10,11 @@

 int main(void){
    while(1){
-       int serial_port = open("/dev/ttyUSB0", O_RDWR);
+//         int serial_port = open("/dev/ttyUSB0", O_RDWR);
+       int serial_port = open("/dev/ttyFAN0", O_RDWR);
        if (serial_port < 0){
-           printf("Can not access /dev/ttyUSB0, please check it out.\n");
+//         printf("Can not access /dev/ttyUSB0, please check it out.\n");
+           printf("Can not access /dev/ttyFAN0, please check it out.\n");
            }

    struct termios tty;
diff --git a/drivers/c/pwmControlFan.c b/drivers/c/pwmControlFan.c
index 1f7d08e..56f34aa 100644
--- a/drivers/c/pwmControlFan.c
+++ b/drivers/c/pwmControlFan.c
@@ -15,7 +15,8 @@ int init_serial( char *serial_name)
    serial_port = open(serial_name, O_RDWR);

    if (serial_port < 0){
-       printf("Can not open /dev/ttyUSB0 serial port ErrorCode: %s\n", strerror(errno));
+//     printf("Can not open /dev/ttyUSB0 serial port ErrorCode: %s\n", strerror(errno));
+       printf("Can not open /dev/ttyFAN0 serial port ErrorCode: %s\n", strerror(errno));
        printf("Please check the /boot/config.txt file and add dtoverlay=dwc2, dr_mode=host and reboot RPi \n");
    }

@@ -103,7 +104,8 @@ int main(void){
    char data[8]={0};
    unsigned int conf_info[8];
    unsigned int cpu_temp=0;
-   init_serial("/dev/ttyUSB0");
+// init_serial("/dev/ttyUSB0");
+   init_serial("/dev/ttyFAN0");
     /* default configuration if /etc/deskpi.conf dose not exist */
    conf_info[0]=40;
    conf_info[1]=25;

diff --git a/drivers/c/safecutoffpower.c b/drivers/c/safecutoffpower.c
index f0b09f9..0d0695b 100644
--- a/drivers/c/safecutoffpower.c
+++ b/drivers/c/safecutoffpower.c
@@ -10,9 +10,11 @@

 int main(void){
    while(1){
-       int serial_port = open("/dev/ttyUSB0", O_RDWR);
+//         int serial_port = open("/dev/ttyUSB0", O_RDWR);
+       int serial_port = open("/dev/ttyFAN0", O_RDWR);
        if (serial_port < 0){
-           printf("Can not access /dev/ttyUSB0, please check it out.\n");
+//         printf("Can not access /dev/ttyUSB0, please check it out.\n");
+           printf("Can not access /dev/ttyFAN0, please check it out.\n");  
            }

    struct termios tty;
diff --git a/drivers/python/pwmControlFan.py b/drivers/python/pwmControlFan.py
index 193c1c4..f9c551e 100644
--- a/drivers/python/pwmControlFan.py
+++ b/drivers/python/pwmControlFan.py
@@ -5,7 +5,7 @@ import time
 import subprocess 

-ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=30)
+ser = serial.Serial("/dev/ttyFAN0", 9600, timeout=30)

 try: 
     while True:
diff --git a/drivers/python/safecutoffpower.py b/drivers/python/safecutoffpower.py
index c9a927f..134c2b2 100644
--- a/drivers/python/safecutoffpower.py
+++ b/drivers/python/safecutoffpower.py
@@ -5,7 +5,8 @@ import serial
 import time 

-ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=30)
+#ser = serial.Serial("/dev/ttyUSB0", 9600, timeout=30)
+ser = serial.Serial("/dev/ttyFAN0", 9600, timeout=30)

 try: 
     while True:
mazzystr commented 2 years ago

A "healthy" project would merge this immediately. I came from ArgonOne and they neglect their upstream the same way.

The diff looks great. One small knit. I suggest the udev rule and c code use device ttyDPIFAN0 so it's very clear on which fan we're dealing with.

iainaff commented 2 years ago

Yeah, good call - naming things is always hard!

mraumala-roku commented 2 years ago

My DeskPi hosts RPI 4 running 64-bit Ubuntu 22.04.1.

I found the /var/log/syslog inundated with following errors (20 GB of it filling the root filesystem after just one day of uptime)...

Please check out /boot/config.txt file
Can not access /dev/ttyUSB0, please check it out.
serial port can not be accessed

Though the solution provided here seems more robust I solved the /dev/ttyUSB0 issue by just getting rid of brltty...

# systemctl stop brltty-udev.service
# systemctl mask brltty-udev.service
# systemctl stop brltty.service
# systemctl disable brltty.service
# apt purge brltty  # uninstalled it in the end

The fan is working now.

neuling10 commented 1 year ago

With your description I was able to solve the fan problem when connecting another device to ttyUSB0. Unfortunately, however, shutdown -h now does not work. I have also done changes in /drivers/c/safecutoffpower.c and /drivers/python/safecutoffpower.py Does that work for you?

My DeskPi hosts RPI 4 running 64-bit Raspberry Pi OS. I have tested install.sh and install-raspbios-64bit.sh

yoyojacky commented 8 months ago

My DeskPi hosts RPI 4 running 64-bit Ubuntu 22.04.1.

I found the /var/log/syslog inundated with following errors (20 GB of it filling the root filesystem after just one day of uptime)...

Please check out /boot/config.txt file
Can not access /dev/ttyUSB0, please check it out.
serial port can not be accessed

Though the solution provided here seems more robust I solved the /dev/ttyUSB0 issue by just getting rid of brltty...

# systemctl stop brltty-udev.service
# systemctl mask brltty-udev.service
# systemctl stop brltty.service
# systemctl disable brltty.service
# apt purge brltty  # uninstalled it in the end

The fan is working now.

This method is good for the OS which can not generate /dev/ttyUSB0 device file, due to this file is generated by this overlay: dtoverlay=dwc2,dr_mode=host, and it will detect the MCU's serial port ,but brltty service will occupy this device file name, so that this is best solution for this issue.