【问题标题】:Linux USB device driver misconceptionLinux USB 设备驱动误解
【发布时间】:2014-04-14 21:26:10
【问题描述】:

我的问题会比较模糊,但我会尽可能详细地解释我要解决的问题。

尝试学习 Linux 内核 USB 堆栈我已经开始考虑为我的基于 ARM M0+ MCU 的 Atmel 评估板制作一个简单的 USB 驱动程序,以脱离 Windows 工具(Visual Studio 插件)。

我花了几天时间学习内核的 USB API 并得出了如何制作这个的结论。我的驱动程序旨在使我的板通过 USB 电缆连接到 PC,就像一个简单的 USB 闪存驱动器一样。然后,我可以轻松地使用我编写的新版本固件对其进行编程。

我发现我需要找出包含端点(管道) 负责与闪存交互。然后我可以将其映射到字符设备,并使用struct file_operations 结构中描述的标准 I/O 操作与它进行交互。

只需在由 USB 核心子系统创建的 /proc/* 文件描述符上使用 cat 我调查了负责与闪存交互的 接口 持有批量端点(同样,这些术语来自充当“描述符”的 USB 规范 (CMIIAW)。 Linux 内核 USB 核心子系统提供了简洁的接口来与不同类型的端点进行通信,无论是 controlinterruptbulk 还是 asynchronous em> 端点。

现在我离我的问题更近了。

另外,两个 USB 设备之间通信的主要传输单元是称为 urb 的抽象 - 你分配它,你填充它,你把它发送到 USB 核心子系统,如果它是 IN 类型,你读取它urb,最后,你释放它。让我感到困惑并且与我的问题密切相关的是下一个 API include/linux/usb.h

static inline void usb_fill_bulk_urb(struct urb *urb,
                                     struct usb_device *dev,
                                     unsigned int pipe,
                                     void *transfer_buffer,
                                     int buffer_length,
                                     usb_complete_t complete_fn,
                                     void *context)

假设我已经从开发板的数据表中获得了关于在哪里编写程序代码的信息。假设我们有0x00100 - 0x10000 内存区域。我将编译我的代码,获取一个二进制文件,然后使用标准 Linux 工具或编写一个简单的用户空间包装应用程序我将使用 lseek 将文件的偏移量设置为 0x00100write 系统调用提供一个缓冲区(二进制之前编译的)和它的长度。

在内核空间中,我将不得不在write系统调用处理程序中分配urb,用从用户空间发送的缓冲区填充它并将这个urb提交到USB核心。

但是我找不到如何指定lseek 之前设置的偏移量的方法。我错过了什么吗?也许我错过了一些概念,或者我看错了?

【问题讨论】:

  • 设备必须运行一些代码(bootloader)来处理传入的请求块。 Atmel 微控制器通常具有SAM-BA。他们已经有免费的 Linux 工具来做你描述的事情,所以我不确定是否有任何关于用于与 SAM-BA 通信的协议的文档;我认为这就是您需要找到(或通过 USB 嗅探观察)来完成您的驱动程序的内容。
  • @NominalAnimal 是的,你是对的。写下这个作为答案,我会撞到它并发表评论,解释我在您对 SAM-BA 的建议后发现的内容。
  • 回答并接受你自己的问题是完全可以的,在这种情况下,我认为这也是很有道理的。你应该描述你最初错过了什么,以及你的发现是什么。 (我关心事实和帮助,而不是声誉或社会问题。)请记住,未来的读者可能会通过网络搜索找到您的问题,尝试解决类似的问题,以及您是否可以为他们提供足够的信息来帮助他们解决他们的问题,这肯定值得您付出一些努力吗?
  • @NominalAnimal 当然。今晚晚些时候我会做出答复。
  • 在内核中没有理由这样做。如果它真的是一个 USB 大容量存储设备,那么内核的驱动程序应该处理它。否则,在用户空间使用 libusb 或直接使用用户空间 USB API 与它交谈。如果它是一个损坏的大容量存储设备(例如第一代 ST 发现板),在告诉内核大容量存储驱动程序忽略它之后,您可能仍想在用户空间与它交谈。跨度>

标签: c linux linux-kernel usb linux-device-driver


【解决方案1】:

当您的嵌入式 Linux 设备充当 USB 大容量存储设备时,将卸载作为 Linux 设备上的外围设备的闪存,并加载小工具驱动程序。 Linux 然后失去对闪存的控制,现在连接到 Linux 设备的 PC 完全控制了闪存。这是因为闪存作为 USB 设备只能有一个 USB 主机。

小工具驱动程序纯粹在内核空间中工作。它不从/向用户空间接收或传输数据。它调用 vfs_read() 和 vfs_write() 来访问闪存上的文件,并带有一个字段偏移量。偏移量来自您的主机 - Windows PC 发送的 USB 命令。

【讨论】:

  • 它不是 Linux 设备。它只有 128Kb 的闪存,我担心它无法承受 Linux 这样的野兽。事实上,它是一台运行 Linux 的 PC。我要开发 USB host 驱动程序,而不是 gadget
  • 好的,我现在明白你的问题了。也许偏移量信息包含在结构urb或上下文中,可以通过函数设置?
  • 这就是我正在寻找的,还没有成功。
【解决方案2】:

无法使用 USB 子系统的 API 指定偏移量。我误解了 USB 作为通信协议的整个概念,我不明智。您必须首先了解您的设备用于与他人通信的底层协议。

如果您的设备充当 USB HID 设备,那么学习如何与 USB HID 设备交换数据的规范是可行的方法。如果有专有的东西,那么您只能对其进行逆向工程(在存在设备驱动程序的系统上使用嗅探器侦听 USB 数据包)。

至于我的开发板,它具有嵌入式调试器,除了作为调试器本身之外,它还用作通信模块。具体来说,我的设备配备了 EDBG,here 是它用于通信的协议描述的链接。

【讨论】:

    猜你喜欢
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多