1

I am looking to write a program that waits indefinitely for an event, in this case, for USB/s to be plugged in and to do some after action that.

I intend to write it in C or Python.

The question is, how can the program be notified when the event has happened (a USB device is plugged in)?

Secondly, if it were done in Python, is there a less resource-intensive way of waiting for the event besides looping?

  • in linux check out udev , it has some example rules. /etc/udev should a place to start or a directory where udev conf files is located. man udev – Jetchisel Jan 28 '20 at 08:48

1 Answers1

4

On Linux, you can, thanks to udev.

  1. Identify your usb device with udevadm info -a /dev/yourdevice. See Writing udev rules.

  2. from your device information, create a udev rule:

    SUBSYSTEM=="zzz", ATTRS{idVendor}=="xxx", ATTRS{idProduct}=="yyy",  RUN+="/usr/bin/my_signaler /dev/%k
    
  3. write your signaler program (in my udev rule, it's located at /usr/bin/my_sampler):

    #! /bin/bash
    NEW_DEVICE="$1"
    TARGETS=$(pgrep program_name)
    for proc in $TARGETS
    do
        kill -s SIGUSR1 $proc
    done
    
  4. Make your program handle the SIGUSR1

    #include <stdio.h>
    #include <signal.h> 
    #include <unistd.h>
    
    void wakeup(int sig) {
         printf("go check /dev" );
    }
    
    int main(void) {
        signal(SIGUSR1, wakeup);
    
        while (1) { 
            /* if the SIGUSR1 signal is received while sleep is waiting, sleep will return*/
            sleep(20);
        }
        return 0;
    }
    
Mathieu
  • 2,719
  • just out of curiousity, where would output from printf() land ? tty ? console ? file ? – Archemar Jan 28 '20 at 09:39
  • In that case, in the standard output. This illustration program is to be launched from a console. – Mathieu Jan 28 '20 at 09:45
  • @Mathieu Hi. I've found this answer helpful except for two things: 1. Instead of printing Go check /dev, the console just notifies me of a User defined signal 1. 2. If I were to omit the ATTRS{idProduct} and ATTRS{idVendor} in the udev rule, will that make this solution general enough for all USB devices identified as sda? – user942937 Feb 05 '20 at 19:12
  • @user942937 On 1., I don't know what happens, on 2., you can change ATTRS{}==... by KERNEL="sda" to match sda. – Mathieu Feb 06 '20 at 08:45
  • @Mathieu: I got it working properly now, except for every USB device plugged in, the event is triggered twice. I suspsect this might be because the USB port itself is registering an event. Also, removing the USB port triggers two additional events. Is there a way to exclude a particular device from triggering the event and to restrict the event to connecting a device? – user942937 Mar 11 '20 at 04:58
  • @user942937 : Seems similar to one of my old problem: https://unix.stackexchange.com/a/253019/15601. Can you post the udev rule you use? I guess you need something like ACTION=="ADD" somewhere... – Mathieu Mar 11 '20 at 10:07
  • @Mathieu: the udev rule consists of only the SUBSYSTEM and RUN. – user942937 Mar 11 '20 at 11:21
  • @user942937 You'd better have an ACTION to differentiate between plug in and out. udevadm monitor --property may help you – Mathieu Mar 11 '20 at 11:24