Linux 2.6.35 下usb框架程序源码(3)

dev->errors = urb->status;
    } else {
        dev->bulk_in_filled = urb->actual_length;
    }
    dev->ongoing_read = 0;
    spin_unlock(&dev->err_lock);

complete(&dev->bulk_in_completion);
}

static int skel_do_read_io(struct usb_skel *dev, size_t count)
{
    int rv;

/* prepare a read */
    usb_fill_bulk_urb(dev->bulk_in_urb,
            dev->udev,
            usb_rcvbulkpipe(dev->udev,
                dev->bulk_in_endpointAddr),
            dev->bulk_in_buffer,
            min(dev->bulk_in_size, count),
            skel_read_bulk_callback,
            dev);
    /* tell everybody to leave the URB alone */
    spin_lock_irq(&dev->err_lock);
    dev->ongoing_read = 1;
    spin_unlock_irq(&dev->err_lock);

/* do it */
    rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
    if (rv < 0) {
        err("%s - failed submitting read urb, error %d",
            __func__, rv);
        dev->bulk_in_filled = 0;
        rv = (rv == -ENOMEM) ? rv : -EIO;
        spin_lock_irq(&dev->err_lock);
        dev->ongoing_read = 0;
        spin_unlock_irq(&dev->err_lock);
    }

return rv;
}

static ssize_t skel_read(struct file *file, char *buffer, size_t count,
             loff_t *ppos)
{
    struct usb_skel *dev;
    int rv;
    bool ongoing_io;

dev = (struct usb_skel *)file->private_data;

/* if we cannot read at all, return EOF */
    if (!dev->bulk_in_urb || !count)
        return 0;

/* no concurrent readers */
    rv = mutex_lock_interruptible(&dev->io_mutex);
    if (rv < 0)
        return rv;

if (!dev->interface) {        /* disconnect() was called */
        rv = -ENODEV;
        goto exit;
    }

/* if IO is under way, we must not touch things */
retry:
    spin_lock_irq(&dev->err_lock);
    ongoing_io = dev->ongoing_read;
    spin_unlock_irq(&dev->err_lock);

if (ongoing_io) {
        /* nonblocking IO shall not wait */
        if (file->f_flags & O_NONBLOCK) {
            rv = -EAGAIN;
            goto exit;
        }
        /*
         * IO may take forever
         * hence wait in an interruptible state
         */
        rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
        if (rv < 0)
            goto exit;
        /*
         * by waiting we also semiprocessed the urb
         * we must finish now
         */
        dev->bulk_in_copied = 0;
        dev->processed_urb = 1;
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwxzgx.html