title: Linux kernel module to read out GPS device via USB
body: <p>I'm writing a Linux kernel module to read out a GPS device (a <a href="http://www.u-blox.com/de/gps-modules/pvt-modules/neo-7.html" rel="nofollow">u-blox NEO-7</a>) via USB by using the book <a href="http://www.makelinux.net/ldd3/" rel="nofollow">Linux Device Drivers</a>.</p>
  
  <p>I already can probe and read out data from the device successfully. But, there is a problem when reading the device with multiple applications simultaneously (I used "cat /dev/ublox" to read indefinitely). When the active/reading applications is cancelled via "Ctrl + C", the next reading attempt from the other application fails (exactly method call <strong>usb_submit_urb(...)</strong> returns <strong>-EINVAL</strong>).</p>
  
  <p>I use following ideas for my implementation:</p>
  
  <ul>
  <li>The kernel module methods should be re-entrant. Therefore, I use a mutex to protect critical sections. E.g. allowing only one reader simultaneously.</li>
  <li>To safe ressources, I reuse the <a href="https://www.kernel.org/doc/htmldocs/usb/API-struct-urb.html" rel="nofollow">struct urb</a> for different reading requests (see an <a href="http://www.makelinux.net/ldd3/chp-13-sect-3" rel="nofollow">explanation</a>)</li>
  <li>Device-specific data like USB endpoint address and so on is held in a <strong>device-specific struct</strong> called <strong>ublox_device</strong>.</li>
  <li>After submitting the USB read request, the calling process is sent to sleep until the asynchronous complete handler is called.</li>
  </ul>
  
  <p>I verified that the ideas are implemented correctly: I have run two instances of "cat /dev/ublox" simultaneously and I got the correct output (only one instance accessed the critical read section at a time). And also reusing the "struct urb" is working. Both instances read out data alternatively.</p>
  
  <p>The problem only occurs if the currently active instance is cancelled via "Ctrl + C". I can solve the problem by not reusing the "struct urb" but I would like to avoid that. I.e. by allocating a new "struct urb" for each read request via <a href="https://www.kernel.org/doc/htmldocs/usb/API-usb-alloc-urb.html" rel="nofollow">usb_alloc_urb(...)</a> (usually it is allocated once when probing the USB device).</p>
  
  <p>My code follows the <a href="https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/usb-skeleton.c?id=refs/tags/v3.16-rc7" rel="nofollow">USB skeleton driver</a> from Greg Kroah-Hartman who also reuse the "struct urb" for different reading requests.</p>
  
  <p>Maybe someone has a clue what's going wrong here.</p>
  
  <p>The complete code can be found on <a href="http://pastebin.com/UUxsrtAk" rel="nofollow">pastebin</a>. Here is a small excerpt of the read method and the USB request complete handler.</p>
  
  <pre><code>static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
  {
          struct ublox_device *ublox_device = file-&gt;private_data;
          ...
          return_value = mutex_lock_interruptible(&amp;ublox_device-&gt;bulk_in_mutex);
          if (return_value &lt; 0)
                  return -EINTR;
          ...
  retry:
          usb_fill_bulk_urb(...);
  
          ublox_device-&gt;read_in_progress = 1;
  
          /* Next call fails if active application is cancelled via "Ctrl + C" */   
          return_value = usb_submit_urb(ublox_device-&gt;bulk_in_urb, GFP_KERNEL);
          if (return_value) {
                  printk(KERN_ERR "usb_submit_urb(...) failed!\n");
                  ublox_device-&gt;read_in_progress = 0;
                  goto exit;
          }
  
          /* Go to sleep until read operation has finished */
          return_value = wait_event_interruptible(ublox_device-&gt;bulk_in_wait_queue, (!ublox_device-&gt;read_in_progress));
          if (return_value &lt; 0)
                  goto exit;
          ...
  exit:
          mutex_unlock(&amp;ublox_device-&gt;bulk_in_mutex);
          return return_value;
  }
  
  static void ublox_read_bulk_callback(struct urb *urb)
  {
          struct ublox_device *ublox_device = urb-&gt;context;
          int status = urb-&gt;status;
  
          /* Evaluate status... */
          ...
          ublox_device-&gt;transferred_bytes = urb-&gt;actual_length;
          ublox_device-&gt;read_in_progress = 0;
  
          wake_up_interruptible(&amp;ublox_device-&gt;bulk_in_wait_queue);
  }
  </code></pre>