我正在编写Linux内核模块,使用书籍u-blox NEO-7通过USB读取GPS设备(Linux Device Drivers)。
我已经可以成功探测并读出设备中的数据。但是,同时读取具有多个应用程序的设备时出现问题(我使用" cat / dev / ublox"无限期阅读)。当通过" Ctrl + C"取消活动/阅读应用程序时,来自另一个应用程序的下一次阅读尝试失败(确切的方法调用 usb_submit_urb(...)返回 -EINVAL )。
我将以下想法用于实施:
我验证了这些想法是否正确实施:我已经运行了两个" cat / dev / ublox"同时我得到了正确的输出(一次只有一个实例访问了关键的读取部分)。并且还重复使用" struct urb"工作中。两个实例都交替读出数据。
仅当通过" Ctrl + C"取消当前活动的实例时,才会出现此问题。我可以通过不重用" struct urb"来解决问题。但我想避免这种情况。即通过分配一个新的" struct urb"对于每个通过usb_alloc_urb(...)的读取请求(通常在探测USB设备时分配一次)。
我的代码遵循Greg Kroah-Hartman的USB skeleton driver,他也重用了" struct urb"针对不同的阅读要求。
也许有人知道这里出了什么问题。
完整的代码可以在pastebin找到。以下是read方法和USB请求完整处理程序的一小部分摘录。
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
if (return_value < 0)
return -EINTR;
...
retry:
usb_fill_bulk_urb(...);
ublox_device->read_in_progress = 1;
/* Next call fails if active application is cancelled via "Ctrl + C" */
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
if (return_value) {
printk(KERN_ERR "usb_submit_urb(...) failed!\n");
ublox_device->read_in_progress = 0;
goto exit;
}
/* Go to sleep until read operation has finished */
return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
if (return_value < 0)
goto exit;
...
exit:
mutex_unlock(&ublox_device->bulk_in_mutex);
return return_value;
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
int status = urb->status;
/* Evaluate status... */
...
ublox_device->transferred_bytes = urb->actual_length;
ublox_device->read_in_progress = 0;
wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
}