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