Kernel

如何將 USB 驅動程序分配給設備

  • April 10, 2015

這個問題有兩個方面:

首先,您如何手動從 USB 設備中分離驅動程序並連接另一個驅動程序?例如,我有一個設備在連接時會自動使用 usb-storage 驅動程序。

usbview 輸出

Vendor Id: xxxx
Product Id: xxxx
...
   Number of Interfaces: 2
   Interface Number: 0
       Name: usb-storage
       Number of Endpoints: 2
       ...
   Interface Number: 1
       Name: (none)
       Number of Endpoints: 2
       ...

我不想使用 usb-storage 驅動程序,因此在我的應用程序中,我使用libusb庫來分離 usb-storage 驅動程序,然後聲明介面。然後,我可以在我的 USB 設備和我的主機 Linux 系統上執行的應用程序之間發送數據。

如何在應用程序之外手動分離驅動程序?


其次,如何自動分配驅動程序以附加到設備外掛上?我目前有一個 udev 規則設置來自動設置設備權限:

SUBSYSTEM=="usb", ATTR{idVendor}=="xxxx", MODE="0666"

我可以使用 udev 規則將驅動程序分配給 USB 設備上的特定介面嗎?例如,如果我希望在介面 0 上自動使用 usbnet 模組而不是 usb-storage,這在 udev 中是否可行?

對於問題的第一部分,我已經看過並且找不到比您已經使用 libusb 做的更好的方法來分離 USB 驅動程序。

至於問題的第二部分,udev 可以驅動程序載入做出反應,但不能強制將特定驅動程序分配給設備。

Linux 核心中的每個驅動程序都負責一個或多個設備。驅動程序本身選擇它支持的設備。它以程式方式執行此操作,即通過檢查設備的供應商和產品 ID,或者,如果這些不可用(例如舊設備),則執行一些自動檢測啟發式和健全性檢查。一旦驅動程序確信它找到了它支持的設備,它就會將自己連接到它。簡而言之,您通常不能強制特定驅動程序使用特定設備。然而,有時,設備驅動程序對它所接受的東西是慷慨的,並且設備可以在它不知道的情況下工作。您的里程會有所不同!過去,我不得不手動將奇怪的 PCI 設備/供應商 ID 添加到應該支持它們的驅動程序中,結果喜憂參半,還發生了一些有趣的核心崩潰。

現在,在模組的情況下,有一個額外的步驟。當檢測到新設備時,核心會喚醒*模組載入器。*它傳遞了一個 ‘modalias’ 字元串,它標識設備,對於 USB 設備看起來像這樣:

usb:v046DpC221d0170dc00dsc00dp00ic03isc00ip00

此字元串包含設備類 ( usb) 和特定於類的資訊(供應商/設備/序列號、設備類等)。每個核心驅動程序都包含一行,例如:

MODULE_ALIAS("usb:...")

其中必須匹配 usbalias(萬用字元用於匹配多個設備)。如果modalias與驅動程序支持的匹配,則載入此驅動程序(或通知新設備,如果它已經存在)。

您可以通過以下方式查看支持的設備(按模式別名)及其相關模組

less /lib/modules/`uname -r`/modules.alias

如果您使用 grep 獲取 usb-storage 設備驅動程序,您會看到它具有一些由供應商和設備 ID 支持的特定設備,並且還將嘗試支持任何具有正確(儲存)類的設備,無論供應商/設備如何.

您可以使用作業系統上的使用者空間機制來影響這一點(/etc/modprobe.d/在 Debian 和朋友上)。您可以將模組列入黑名單,也可以指定要由 modalias 載入的模組,就像modules.alias文件一樣(並使用相同的語法)。depmod -a然後將重新生成模組載入器的模式。

然而,即使你可以把這匹特殊的馬帶到水邊,但你不能讓他喝水。如果驅動程序不支持您的設備,它應該忽略它。

這是一般情況下的理論。

實際上,在 USB 的情況下,我看到您的設備似乎有兩個介面,其中一個是儲存介面。核心將附加到整個設備的儲存介面。如果另一個介面具有正確的類,usbnet驅動程序可以附加到它。是的,您可以將多個驅動程序連接到同一個物理設備,因為 USB 設備導出多個介面(例如,我的 Logitech G15 鍵盤導出兩個,因為它有一個鍵盤設備和一個 LCD 螢幕,每個都由單獨的驅動程序處理) .

未檢測到 USB 設備的第二個介面這一事實表明核心缺乏支持。無論如何,您都可以使用 列出設備介面/端點的詳細資訊lsusb -v | less,然後向下滾動到您的特定設備(如果您願意,可以通過設備:供應商 ID 或 USB 路徑限制輸出)。

請注意:關於 USB 設備的邏輯結構,我在這裡稍微簡化了一點。責怪USB聯盟。:)

引用自:https://unix.stackexchange.com/questions/26132