title: Using a userspace driver in Linux daemon
body: <p>I'm trying to write a daemon that monitors the state of a USB GPIO device (Velleman VM167) and will then act on changed.</p>
  <p>I've found a userspace driver (<a href="https://github.com/rahlskog/VM167" rel="nofollow noreferrer">https://github.com/rahlskog/VM167</a>) and have set some /etc/udev rules and ldconfig paths so that I can run the test and it works as expected.</p>
  <p>If I compile the following it works as expected:</p>
  <pre><code>#include &lt;iterator&gt;
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;sstream&gt;
  #include &lt;iostream&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;syslog.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;vector&gt;
  #include &quot;VM167.h&quot;
  
  int test_openDevices();
  void test_readWriteDigital(int card);
  void test_readAnalog(int card);
  void test_PWM(int card);
  
  int main(void)
  {
     syslog(LOG_INFO, &quot;Loop&quot;);
     int devices;
          devices = OpenDevices();
          if (devices == 0)
          {
                  syslog(LOG_ERR, &quot;Driver error condition, exiting&quot;);
                  //fflush(stdout);
                  //return -1;
          }
          else if (devices == -1)
          {
                  syslog(LOG_ERR, &quot;No devices found on system, exiting\n&quot;);
                  //fflush(stdout);
                  //return -1;
          }
          int ver = VersionDLL();
          syslog(LOG_INFO, &quot;DLL Version: %d.%d.%d.%d\n&quot;, (ver&gt;&gt;24), (ver&gt;&gt;16)&amp;0xFF, (ver&gt;&gt;8)&amp;0xFF, ver&amp;0xFF);
  }
  </code></pre>
  <p>Syslog:</p>
  <pre><code>Nov  4 01:12:12 testserver console: Loop
  Nov  4 01:12:12 testserver console: DLL Version: 0.1.0.19
  
  </code></pre>
  <p>However when I add this to a daemon template I can no longer see the USB card...</p>
  <pre><code>#include &lt;dirent.h&gt;
  #include &lt;iterator&gt;
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;sstream&gt;
  #include &lt;iostream&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;syslog.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;vector&gt;
  #include &quot;VM167.h&quot;
  
  int test_openDevices();
  void test_readWriteDigital(int card);
  void test_readAnalog(int card);
  void test_PWM(int card);
  
  void do_heartbeat()
  {
     // TODO: implement processing code to be performed on each heartbeat
     syslog(LOG_INFO, &quot;Loop&quot;);
     int devices;
          devices = OpenDevices();
          if (devices == 0)
          {
                  syslog(LOG_ERR, &quot;Driver error condition, exiting&quot;);
                  //fflush(stdout);
                  //return -1;
          }
          else if (devices == -1)
          {
                  syslog(LOG_ERR, &quot;No devices found on system, exiting\n&quot;);
                  //fflush(stdout);
                  //return -1;
          }
          int ver = VersionDLL();
          syslog(LOG_INFO, &quot;DLL Version: %d.%d.%d.%d\n&quot;, (ver&gt;&gt;24), (ver&gt;&gt;16)&amp;0xFF, (ver&gt;&gt;8)&amp;0xFF, ver&amp;0xFF);
  }
  
  // For security purposes, we don't allow any arguments to be passed into the daemon
  int main(void)
  {
     // Define variables
     pid_t pid, sid;
  
     // Fork the current process
     pid = fork();
     // The parent process continues with a process ID greater than 0
     if(pid &gt; 0)
     {
        exit(EXIT_SUCCESS);
     }
     // A process ID lower than 0 indicates a failure in either process
     else if(pid &lt; 0)
     {
        exit(EXIT_FAILURE);
     }
     // The parent process has now terminated, and the forked child process will continue
     // (the pid of the child process was 0)
  
     // Since the child process is a daemon, the umask needs to be set so files and logs can be written
     umask(0);
  
     // Open system logs for the child process
     openlog(&quot;Daemon-GPIO&quot;, LOG_NOWAIT | LOG_PID, LOG_USER);
     syslog(LOG_NOTICE, &quot;Successfully started Daemon-GPIO&quot;);
  
     // Generate a session ID for the child process
     sid = setsid();
     // Ensure a valid SID for the child process
     if(sid &lt; 0)
     {
        // Log failure and exit
        syslog(LOG_ERR, &quot;Could not generate session ID for child process&quot;);
  
        // If a new session ID could not be generated, we must terminate the child process
        // or it will be orphaned
        exit(EXIT_FAILURE);
     }
  
     // Change the current working directory to a directory guaranteed to exist
     if((chdir(&quot;/&quot;)) &lt; 0)
     {
        // Log failure and exit
        syslog(LOG_ERR, &quot;Could not change working directory to /&quot;);
  
        // If our guaranteed directory does not exist, terminate the child process to ensure
        // the daemon has not been hijacked
        exit(EXIT_FAILURE);
     }
  
     // A daemon cannot use the terminal, so close standard file descriptors for security reasons
     close(STDIN_FILENO);
     close(STDOUT_FILENO);
     close(STDERR_FILENO);
  
     // Daemon-specific intialization should go here
     const int SLEEP_INTERVAL = 5;
  
     // Enter daemon loop
     while(1)
     {
        syslog(LOG_INFO, &quot;Starting helper loop&quot;);
        // Execute daemon heartbeat, where your recurring activity occurs
        do_heartbeat();
  
        // Sleep for a period of time
        sleep(SLEEP_INTERVAL);
     }
  
     // Close system logs for the child process
     syslog(LOG_NOTICE, &quot;Stopping Daemon-GPIO&quot;);
     closelog();
  
     // Terminate the child process when the daemon completes
     exit(EXIT_SUCCESS);
  }
  </code></pre>
  <p>Syslog:</p>
  <pre><code>Nov  4 00:18:10 testserver Daemon-GPIO[29638]: Loop
  Nov  4 00:18:10 testserver Daemon-GPIO[29638]: No devices found on system, exiting
  Nov  4 00:18:10 testserver Daemon-GPIO[29638]: DLL Version: 0.1.0.19
  </code></pre>