The program (u50/u60 USB device driver daemon) succeeds from the shell but fails if started upon boot by udev.
I tried to use sd_listen_fds() but it returned 0.
int lonsd; // file descriptor for the new socket
struct ifreq ifr = {0};
struct ifaddrs *ifaddr, *ifa;
int found = 0;
int fd;
int num_fds; // number of file descriptors
// https://insujang.github.io/2018-11-27/udev-device-manager-for-the-linux-kernel-in-userspace/
// Currently, udev is a part of systemd, therefore it uses systemd’s socket protocol.
syslog(LOG_INFO, "%s devstr:%s, ldisc:%d\n", __func__, devstr, ldisc);
lonsd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
if (lonsd < 0) {
syslog(LOG_INFO, "%s socket() failed - must be udev\n", __func__);
lonsd = -EBADF;
//systemd/src/udev/udevd.c:
//static int listen_fds(int* ret_ctrl, int* ret_netlink) {
num_fds = sd_listen_fds(true);
if (num_fds < 0) {
syslog(LOG_CRIT, "%s sd_listen_fds() failed\n", __func__);
}
syslog(LOG_INFO, "%s num_fds:%d\n", __func__, num_fds);
for (fd = SD_LISTEN_FDS_START; fd < num_fds + SD_LISTEN_FDS_START; fd++) {
if (sd_is_socket(fd, AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)) > 0) {
if (lonsd >= 0) {
syslog(LOG_CRIT, "%s EINVAL: lonsd >= 0\n", __func__);
return -EINVAL;
}
lonsd = fd;
}
}
}
else syslog(LOG_INFO, "%s lonsd:%d\n", __func__, lonsd);
I am porting a driver for a LonWorks USB interface (Bus 003 Device 004: ID 0920:5550 Echelon Co. Echelon U60 FT Network Interface). The u50.ko driver was inserted. When run from the shell, "lonifd" creates a network device.
5: lon10: <BROADCAST,UP,LOWER_UP> mtu 1280 qdisc fq_codel state UNKNOWN group default qlen 10 link/[2384] inet 44.1.110.125/24 brd 44.1.110.255 scope global lon10 valid_lft forever preferred_lft forever –
But when started by udev, socket() fails.
Per the comments, I changed the rule to start a service. Now it runs "lonifd" upon boot if the device is found, and when the device is plugged in and stops it when it is unplugged.
The revised rule: /etc/udev/rules.d/90-liftd.rules.
SUBSYSTEM=="tty", ATTRS{idVendor}=="0920", ATTRS{idProduct}=="5550", ENV{SYSTEMD_WANTS}+="u60.service"
/etc/systemd/system/u60.service
[Unit]
Description=U60 USB Lontalk Interface
Documentation=
[Service]
ExecStart=/usr/bin/lonifd
Type=exec
Restart=on-failure