简体   繁体   English

Linux USB设备驱动程序误解

[英]Linux USB device driver misconception

My question is going to be rather vague but I will try to explain as detailed as I can what I am trying to resolve. 我的问题将很模糊,但是我将尽我所能解决的问题进行详细解释。

Trying to learn Linux kernel USB stack I have started to think of making a simple USB driver for my Atmel evaluation board based on ARM M0+ MCU to run away from Windows tools (Visual Studio plugin). 在尝试学习Linux内核USB堆栈时,我开始考虑为基于ARM M0 + MCU的Atmel评估板制作一个简单的USB驱动程序,以使其脱离Windows工具(Visual Studio插件)。

I have spent few days learning kernel's USB API and come to conclusion of how to make this. 我花了几天的时间学习内核的USB API,并得出如何做到这一点的结论。 My driver aims to make my board connected to PC through USB cable act like a simple USB flash drive. 我的驱动程序旨在使通过USB电缆连接到PC的电路板就像一个简单的USB闪存驱动器。 Making that I then can easily program it with a new version of firmware written by me. 这样,我便可以使用我编写的新固件版本轻松对其进行编程。

I have found that I need to find out specific interface (I am talking about interface in terms of USB specification, not interface we used to use as a code abstraction) that holds an endpoint (pipe) responsible for interaction with flash memory. 我发现,我需要找出特定的接口(我说的是接口 USB规范的方面,而不是界面我们作为一个抽象的代码使用),它保存的端点(管道)负责与闪存的互动。 And then I can map it to character device and interact with it using standard I/O operations that are described in struct file_operations structure. 然后,我可以映射到字符设备,并使用在struct file_operations结构中描述的标准I / O操作与之交互。

Simply using cat on /proc/* file descriptor that was created by USB Core subsystem I have investigated that interface responsible for interaction with flash memory holds bulk endpoint (likewise, this terms come from USB specification, CMIIAW) that act as a "descriptor". 只需在USB Core子系统创建的/proc/*文件描述符上使用cat ,我就研究了负责与闪存交互的接口拥有大量端点 (同样,该术语来自USB规范CMIIAW),充当“描述符” 。 Linux kernel USB Core subsystem gives neat interfaces to talk to different kind of endpoints whether it control , interrupt , bulk or asynchronous endpoint. Linux内核USB Core子系统提供了整洁的接口来与不同类型的端点进行通信,无论它是控制端点, 中断端点, 批量端点还是异步端点。

Now I have come closer to my very question. 现在,我已经接近我的问题了。

Also the main transfer unit in communication between two USB devices is abstraction called urb - you allocate it, you fill it, you send it to USB Core subsystem, you read it if it was IN type of urb and, finally, you free it. 同样,两个USB设备之间通信的主要传输单元是称为urb的抽象-分配它,填充它,将其发送到USB Core子系统,如果它是urb的 IN类型,则阅读该文件,最后释放它。 What is confusing for me and tightly related to my question is the next API include/linux/usb.h : 下一个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)

Assume I have obtained an information from board's datasheet about where to write a program code. 假设我从电路板的数据表中获得了有关在哪里编写程序代码的信息。 Let's say, we have 0x00100 - 0x10000 memory region. 比方说,我们有0x00100 - 0x10000内存区域。 I will compile my code, obtain a binary and then using standard Linux tools or writing a simple user-space wrapper application I will use lseek to set file's offset to 0x00100 and write system call provided with a buffer (binary compiled previously) and it's length. 我将编译我的代码,获取一个二进制文件,然后使用标准的Linux工具或编写一个简单的用户空间包装器应用程序,我将使用lseek将文件的偏移量设置为0x00100write带有缓冲区的系统调用(先前已编译的二进制文件)及其长度。

In kernel space, I will have to allocate urb in write system call handler, fill it with a buffer sent from user space and submit this urb to USB Core. 在内核空间中,我将不得不在write系统调用处理程序中分配urb ,并用从用户空间发送的缓冲区填充该urb ,然后将该urb提交给USB Core。

BUT I can not find a way how to specify an OFFSET set earlier by lseek . 但是我找不到一种方法来指定由lseek设置的OFFSET。 Do I miss something? 我想念什么吗? Maybe I missed some concepts or, perhaps, I am watching in a wrong way? 也许我错过了一些概念,或者我看错了方向?

When your embedded Linux device acts as a USB mass storage device, the flash as a peripheral on Linux device is unmounted, and the gadget driver is loaded. 当嵌入式Linux设备充当USB大容量存储设备时,将卸载Linux设备上作为外围设备的闪存,并加载小工具驱动程序。 Linux then loses control to the flash, and now the PC connected to your Linux device fully controls the flash. 然后,Linux失去了对闪存的控制,现在连接到Linux设备的PC可以完全控制闪存。 This is because a flash as a USB device can only has one USb host. 这是因为作为USB设备的闪存只能具有一个USB主机。

The gadget driver works purely in kernel space. 小工具驱动程序仅在内核空间中工作。 It does not receive or transmit data from/to user space. 它不从用户空间接收数据或向用户空间传输数据。 It calls vfs_read() and vfs_write() to access the files on the flash, with an field offset. 它调用vfs_read()和vfs_write()来访问闪存中的文件,且具有字段偏移量。 The offset is got from the USB commands sent from your host - Windows PC. 偏移量是从主机-Windows PC发送的USB命令获得的。

There is no way to specify offset using USB subsystem's API. 无法使用USB子系统的API指定偏移量。 I misunderstood whole conception of USB as communication protocol, unwise me. 我误解了USB作为通信协议的整个概念,这是不明智的。 You must first learn underlying protocol your device uses to communicate with others. 您必须首先了解您的设备用于与他人通信的基础协议。

If your device acts as a USB HID device then learning specification of how to exchange data with USB HID device is the way to go. 如果您的设备充当USB HID设备,那么学习如何与USB HID设备交换数据的规范就可以了。 If there is something proprietary then you can do nothing but reverse engineer it (listening USB packets with a sniffer on system where a driver for your device exists). 如果有专有的东西,那么您只能对其进行逆向工程(在设备驱动程序所在的系统上用嗅探器侦听USB数据包)。

As for my board it has embedded debugger that serves as a communication module besides being debugger itself. 至于我的开发板,它具有嵌入式调试器,该调试器除了本身就是调试器之外,还用作通信模块。 Specifically, my device is equipped with EDBG and here is a link on description of protocol it uses for communication. 具体来说,我的设备配备了EDBG, 是其用于通信的协议说明的链接。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM