r = usb_autopm_get_interface(desc->intf);
        if (r < 0)
                goto outnp;
-       r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
-                                                          &desc->flags));
+
+       if (!file->f_flags && O_NONBLOCK)
+               r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
+                                                               &desc->flags));
+       else
+               if (test_bit(WDM_IN_USE, &desc->flags))
+                       r = -EAGAIN;
        if (r < 0)
                goto out;
 
 static ssize_t wdm_read
 (struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
-       int rv, cntr;
+       int rv, cntr = 0;
        int i = 0;
        struct wdm_device *desc = file->private_data;
 
        if (desc->length == 0) {
                desc->read = 0;
 retry:
+               if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
+                       rv = -ENODEV;
+                       goto err;
+               }
                i++;
-               rv = wait_event_interruptible(desc->wait,
-                                             test_bit(WDM_READ, &desc->flags));
+               if (file->f_flags & O_NONBLOCK) {
+                       if (!test_bit(WDM_READ, &desc->flags)) {
+                               rv = cntr ? cntr : -EAGAIN;
+                               goto err;
+                       }
+                       rv = 0;
+               } else {
+                       rv = wait_event_interruptible(desc->wait,
+                               test_bit(WDM_READ, &desc->flags));
+               }
 
+               /* may have happened while we slept */
                if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
                        rv = -ENODEV;
                        goto err;
 
 err:
        mutex_unlock(&desc->rlock);
-       if (rv < 0)
+       if (rv < 0 && rv != -EAGAIN)
                dev_err(&desc->intf->dev, "wdm_read: exit error\n");
        return rv;
 }