我需要制作一个Linux驱动程序来控制某些第三方组件。该组件没有非易失性存储器,因此初始化的一部分涉及到我连续发送一堆USB传输来加载设备固件。
为此,我正在复制this源代码以制作基本的Linux USB驱动程序。当我连接外部组件之前,所有的设置和检测功能似乎都可以正常工作,直到尝试加载固件。
使用以下功能:
static ssize_t skel_write(struct file *file, const char *user_buffer,
size_t count, loff_t *ppos)
{
struct usb_skel *dev;
int retval = 0;
struct urb *urb = NULL;
char *buf = NULL;
size_t writesize = min(count, (size_t)MAX_TRANSFER);
dev = file->private_data;
/* verify that we actually have some data to write */
if (count == 0)
goto exit;
/*
* limit the number of URBs in flight to stop a user from using up all
* RAM
*/
if (!(file->f_flags & O_NONBLOCK)) {
if (down_interruptible(&dev->limit_sem)) {
retval = -ERESTARTSYS;
goto exit;
}
} else {
if (down_trylock(&dev->limit_sem)) {
retval = -EAGAIN;
goto exit;
}
}
spin_lock_irq(&dev->err_lock);
retval = dev->errors;
if (retval < 0) {
/* any error is reported once */
dev->errors = 0;
/* to preserve notifications about reset */
retval = (retval == -EPIPE) ? retval : -EIO;
}
spin_unlock_irq(&dev->err_lock);
if (retval < 0)
goto error;
/* create a urb, and a buffer for it, and copy the data to the urb */
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}
if (copy_from_user(buf, user_buffer, writesize)) {
retval = -EFAULT;
goto error;
}
/* this lock makes sure we don't submit URBs to gone devices */
mutex_lock(&dev->io_mutex);
if (!dev->interface) { /* disconnect() was called */
mutex_unlock(&dev->io_mutex);
retval = -ENODEV;
goto error;
}
/* initialize the urb properly */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, writesize, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
usb_anchor_urb(urb, &dev->submitted);
/* send the data out the bulk port */
retval = usb_submit_urb(urb, GFP_KERNEL);
mutex_unlock(&dev->io_mutex);
if (retval) {
dev_err(&dev->interface->dev,
"%s - failed submitting write urb, error %d\n",
__func__, retval);
goto error_unanchor;
}
/*
* release our reference to this urb, the USB core will eventually free
* it entirely
*/
usb_free_urb(urb);
return writesize;
error_unanchor:
usb_unanchor_urb(urb);
error:
if (urb) {
usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
usb_free_urb(urb);
}
up(&dev->limit_sem);
exit:
return retval;
}
要加载固件,我需要发送大约50个USB事务。大约8点之后,我开始看到错误ERESTARTSYS。发生这种情况之后,所有后续的USB事务都会失败,然后如果我再试一次,我将在第一次尝试的事务中收到错误消息。
基于注释“限制正在运行的URB数量以阻止用户用完所有RAM”,似乎前8个URB已安排好了,但从未解决,此后缓冲区已满,因此所有后续尝试都是拒绝了。
但是,似乎没有其他错误消息发生,尝试进行初始化时,系统仅等待并且不报告尝试的USB事务的任何错误。
我如何确定正在进行的USB交易的状态,以查看为何未进行交易?