Linux-USB 主機端 API¶
Linux 上的 USB 簡介¶
通用序列匯流排 (USB) 用於將主機(如 PC 或工作站)連線到多個外圍裝置。 USB 使用樹結構,主機作為根(系統的主裝置),集線器作為內部節點,外圍裝置作為葉節點(和從裝置)。 現代 PC 支援多個這樣的 USB 裝置樹,通常是幾個 USB 3.0 (5 GBit/s) 或 USB 3.1 (10 GBit/s) 和一些舊的 USB 2.0 (480 MBit/s) 匯流排以備不時之需。
這種主/從不對稱設計是出於多種原因,其中一個原因是易於使用。 物理上不可能混淆上游和下游,或者使用 C 型插頭無關緊要(或者它們內置於外圍裝置中)。 此外,主機軟體不需要處理分散式自動配置,因為預先指定的主節點管理所有這些。
核心開發人員在 2.2 核心系列的早期為 Linux 添加了 USB 支援,並且從那時起一直在進一步開發它。 除了支援每個新一代 USB 之外,各種主機控制器也獲得了支援,添加了新的外圍裝置驅動程式,並引入了用於延遲測量和改進電源管理的高階功能。
Linux 可以在 USB 裝置內部以及控制這些裝置的主機上執行。 但是在這些外圍裝置內部執行的 USB 裝置驅動程式與在主機內部執行的驅動程式所做的事情不同,因此它們被賦予了不同的名稱:gadget drivers。 本文件不包括 gadget drivers。
USB 主機端 API 模型¶
USB 裝置的主機端驅動程式與“usbcore”API 通訊。 有兩種。 一種用於通用驅動程式(透過驅動程式框架公開),另一種用於核心的一部分的驅動程式。 這種核心驅動程式包括集線器驅動程式(管理 USB 裝置樹)和幾種不同型別的主機控制器驅動程式,它們控制單個匯流排。
USB 驅動程式看到的裝置模型相對複雜。
USB 支援四種資料傳輸型別(控制、批次、中斷和同步)。 其中兩個(控制和批次)根據可用頻寬使用頻寬,而另外兩個(中斷和同步)被排程以提供保證的頻寬。
裝置描述模型包括每個裝置的一個或多個“配置”,一次只有一個配置處於活動狀態。 裝置應該能夠以低於其最高速度執行,並且可以提供 BOS 描述符,顯示它們保持完全執行的最低速度。
從 USB 3.0 開始,配置有一個或多個“功能”,這些功能提供通用功能,並組合在一起用於電源管理。
配置或功能具有一個或多個“介面”,每個介面可能具有“備用設定”。 介面可以由 USB “類”規範標準化,也可以特定於供應商或裝置。
USB 裝置驅動程式實際上繫結到介面,而不是裝置。 將它們視為“介面驅動程式”,儘管您可能看不到區分很重要的許多裝置。 大多數 USB 裝置都很簡單,只有一個功能、一個配置、一個介面和一個備用設定。
介面有一個或多個“端點”,每個端點支援一種型別和方向的資料傳輸,例如“批次輸出”或“中斷輸入”。 整個配置在每個方向上最多可以有十六個端點,根據需要在所有介面之間分配。
USB 上的資料傳輸是分組化的; 每個端點都有一個最大資料包大小。 驅動程式通常必須瞭解約定,例如使用“短”(包括零長度)資料包標記批次傳輸的結束。
Linux USB API 支援用於控制和批次訊息的同步呼叫。 它還支援使用名為“URB”(USB 請求塊)的請求結構進行所有型別的資料傳輸的非同步呼叫。
因此,暴露給裝置驅動程式的 USB Core API 涵蓋了相當多的領域。 您可能需要查閱 USB 3.0 規範(可從 www.usb.org 線上免費獲得)以及類或裝置規範。
實際接觸硬體(讀取/寫入暫存器、處理 IRQ 等)的唯一主機端驅動程式是 HCD。 理論上,所有 HCD 都透過相同的 API 提供相同的功能。 實際上,這種情況越來越真實,但仍然存在差異,尤其是在不太常見的控制器上處理故障時。 不同的控制器不一定報告相同的故障方面,並且從故障中恢復(包括軟體引起的故障,如取消連結 URB)尚未完全一致。 裝置驅動程式作者應該重點使用每個不同的主機控制器驅動程式進行斷開連線測試(在裝置處於活動狀態時),以確保驅動程式沒有自己的錯誤,並確保它們不依賴於某些 HCD 特定的行為。
USB 標準型別¶
在 include/uapi/linux/usb/ch9.h 中,您將找到 USB 規範第 9 章中定義的 USB 資料型別。 這些資料型別在整個 USB 中使用,並且在包括此主機端 API、gadget API、usb 字元裝置和 debugfs 介面的 API 中使用。 該檔案本身包含在 include/linux/usb/ch9.h 中,後者還包含一些用於操作這些資料型別的實用程式的宣告; 實現位於 drivers/usb/common/common.c 中。
-
const char *usb_ep_type_string(int ep_type)¶
返回端點型別的可讀名稱。
引數
int ep_type要返回可讀名稱的端點型別。 如果它不是任何型別:USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT},通常由 usb_endpoint_type() 獲得,則將返回字串“unknown”。
-
const char *usb_otg_state_string(enum usb_otg_state state)¶
返回 OTG 狀態的可讀名稱。
引數
enum usb_otg_state state要返回可讀名稱的 OTG 狀態。 如果它不是 usb_otg_state 列舉中定義的任何狀態,則將返回“UNDEFINED”。
-
const char *usb_speed_string(enum usb_device_speed speed)¶
返回速度的可讀名稱。
引數
enum usb_device_speed speed要返回可讀名稱的速度。 如果它不是 usb_device_speed 列舉中定義的任何速度,則將返回 USB_SPEED_UNKNOWN 的字串。
引數
struct device *dev指向給定 USB 控制器裝置的指標
描述
該函式從屬性“maximum-speed”獲取最大速度字串,並返回相應的 enum usb_device_speed。
-
enum usb_ssp_rate usb_get_maximum_ssp_rate(struct device *dev)¶
獲取支援 SuperSpeed Plus 的裝置的信令速率生成和通道數。
引數
struct device *dev指向給定 USB 控制器裝置的指標
描述
如果來自“maximum-speed”屬性的字串是 super-speed-plus-genXxY,其中“X”是生成編號,“Y”是通道數,則此函式返回相應的 enum usb_ssp_rate。
-
const char *usb_state_string(enum usb_device_state state)¶
返回狀態的可讀名稱。
引數
enum usb_device_state state要返回可讀名稱的狀態。 如果它不是 usb_device_state_string 列舉中的任何狀態裝置,則將返回字串 UNKNOWN。
引數
struct device *dev指向給定裝置的指標
描述
該函式從屬性“role-switch-default-mode”獲取字串,並返回相應的 enum usb_dr_mode。
-
unsigned int usb_decode_interval(const struct usb_endpoint_descriptor *epd, enum usb_device_speed speed)¶
將 bInterval 解碼為以 1us 為單位表示的時間
引數
const struct usb_endpoint_descriptor *epd端點的描述符
enum usb_device_speed speed端點工作的速度
描述
函式返回以 1us 為單位表示的為端點提供資料傳輸服務的時間間隔。
-
enum usb_dr_mode of_usb_get_dr_mode_by_phy(struct device_node *np, int arg0)¶
獲取與給定 phy device_node 關聯的控制器裝置的雙重角色模式
引數
struct device_node *np指向給定 phy device_node 的指標
int arg0對於 #phy-cells >= 1 的 phy 的 phandle args[0],或對於沒有 phy-cells 的 phy 的 -1
描述
在 dts 中,usb 控制器與 phy 裝置關聯。 該函式從與給定 phy 裝置節點關聯的控制器的屬性“dr_mode”獲取字串,並返回相應的 enum usb_dr_mode。
-
bool of_usb_host_tpl_support(struct device_node *np)¶
用於獲取給定目標主機(非 PC 主機)是否支援目標外圍裝置列表
引數
struct device_node *np指向給定 device_node 的指標
描述
該函式獲取目標主機是否支援 TPL
-
int of_usb_update_otg_caps(struct device_node *np, struct usb_otg_caps *otg_caps)¶
用於根據 DT 中傳遞的屬性更新 usb otg 功能。
引數
struct device_node *np指向給定 device_node 的指標
struct usb_otg_caps *otg_caps指向要設定的目標 usb_otg_caps 的指標
描述
該函式更新 otg 功能
引數
struct device *dev指向用於查詢配套裝置的指標
描述
從平臺匯流排查詢配套裝置。
獲取返回的 struct device 的引用,該引用在使用後需要刪除。
返回
成功時,指向配套裝置的指標,失敗時為 NULL。
此外,drivers/usb/common/debug.c 中定義了一些用於建立除錯輸出的有用函式。
主機端資料型別和宏¶
主機端 API 向驅動程式公開了多個層,其中一些層比其他層更必要。 這些層支援主機端驅動程式和裝置的生命週期模型,並支援透過 usbcore 將緩衝區傳遞給某些 HCD,這些 HCD 為裝置驅動程式執行 I/O。
-
struct usb_host_endpoint¶
主機端端點描述符和佇列
定義:
struct usb_host_endpoint {
struct usb_endpoint_descriptor desc;
struct usb_ss_ep_comp_descriptor ss_ep_comp;
struct usb_ssp_isoc_ep_comp_descriptor ssp_isoc_ep_comp;
struct usb_eusb2_isoc_ep_comp_descriptor eusb2_isoc_ep_comp;
struct list_head urb_list;
void *hcpriv;
struct ep_device *ep_dev;
unsigned char *extra;
int extralen;
int enabled;
int streams;
};
成員
desc此端點的描述符,wMaxPacketSize 採用本機位元組順序
ss_ep_comp此端點的 SuperSpeed 輔助描述符
ssp_isoc_ep_comp此端點的 SuperSpeedPlus 同步輔助描述符
eusb2_isoc_ep_comp此端點的 eUSB2 同步輔助描述符
urb_list排隊到此端點的 URB; 由 usbcore 維護
hcpriv供 HCD 使用; 通常儲存硬體 dma 佇列頭 (QH),每個 URB 有一個或多個傳輸描述符 (TD)
ep_dev用於 sysfs 資訊的 ep_device
extra此端點之後的配置中的描述符
extralen有多少位元組的“extra”有效
enabledURB 可以提交到此端點
streams在端點上分配的 USB-3 流的數量
描述
USB 請求始終排隊到給定的端點,該端點由給定 USB 配置中活動介面內的描述符標識。
-
struct usb_interface¶
usb 裝置驅動程式與之通訊的內容
定義:
struct usb_interface {
struct usb_host_interface *altsetting;
struct usb_host_interface *cur_altsetting;
unsigned num_altsetting;
struct usb_interface_assoc_descriptor *intf_assoc;
int minor;
enum usb_interface_condition condition;
unsigned sysfs_files_created:1;
unsigned ep_devs_created:1;
unsigned unregistering:1;
unsigned needs_remote_wakeup:1;
unsigned needs_altsetting0:1;
unsigned needs_binding:1;
unsigned resetting_device:1;
unsigned authorized:1;
enum usb_wireless_status wireless_status;
struct work_struct wireless_status_work;
struct device dev;
struct device *usb_dev;
struct work_struct reset_ws;
};
成員
altsetting介面結構陣列,每個可選擇的備用設定都有一個。 每個都包含一組端點配置。 它們將不按特定順序排列。
cur_altsetting當前備用設定。
num_altsetting定義的備用設定數量。
intf_assoc介面關聯描述符
minor分配給此介面的次要編號,如果此介面繫結到使用 USB 主要編號的驅動程式。 如果此介面不使用 USB 主要編號,則應不使用此欄位。 驅動程式應在驅動程式的 probe() 函式中設定此值,在透過呼叫
usb_register_dev()從 USB 核心為其分配了次要編號之後。condition介面的繫結狀態:未繫結、正在繫結(在 probe() 中)、繫結到驅動程式或正在取消繫結(在 disconnect() 中)
sysfs_files_createdsysfs 屬性存在
ep_devs_created端點子偽裝置存在
unregistering取消註冊介面時設定的標誌
needs_remote_wakeup驅動程式在自動掛起期間需要遠端喚醒功能時設定的標誌。
needs_altsetting0已推遲 altsetting 0 的設定介面請求時設定的標誌。
needs_binding在重置或掛起操作後應重新探測或取消繫結驅動程式時設定的標誌,它不支援。
resetting_deviceUSB 核心重置裝置,因此使用 alt 設定 0 作為當前設定; 重置後需要頻寬分配。
authorized這允許(取消)授權單個介面,而不是與裝置授權相反的整個裝置。
wireless_status如果 USB 裝置使用接收器/發射器組合,則發射器是否已連線。
wireless_status_work用於從原子上下文中排程無線狀態更改。
dev驅動程式模型對此裝置的檢視
usb_dev如果介面繫結到 USB 主要編號,則這將指向該裝置的 sysfs 表示。
reset_ws用於從原子上下文中排程重置。
描述
USB 裝置驅動程式連線到物理裝置上的介面。 每個介面封裝了一個單獨的高階功能,例如將音訊流饋送到揚聲器或報告音量控制中的更改。 許多 USB 裝置只有一個介面。 用於與介面端點通訊的協議可以在 usb “類”規範中定義,也可以由產品的供應商定義。 (預設)控制端點是每個介面的一部分,但從未列在介面的描述符中。
繫結到介面的驅動程式可以使用標準驅動程式模型呼叫,例如 dev_get_drvdata() 在此結構的 dev 成員上。
每個介面可能具有備用設定。 裝置的初始配置設定 altsetting 0,但裝置驅動程式可以使用 usb_set_interface() 更改該設定。 備用設定通常用於控制週期性端點的使用,例如透過讓不同的端點使用不同數量的保留 USB 頻寬。 所有符合標準的 USB 裝置,使用同步端點,將在非預設設定中使用它們。
USB 規範指出,備用設定編號必須從 0 執行到小於備用設定總數的一個數字。 但是某些裝置設法弄亂了這一點,並且無論如何都不能保證結構以數字順序儲存。 使用 usb_altnum_to_altsetting() 在 altsetting 陣列中查詢基於其編號的備用設定。
-
void usb_set_intfdata(struct usb_interface *intf, void *data)¶
將驅動程式特定資料與介面關聯
引數
struct usb_interface *intfUSB 介面
void *data驅動程式資料
描述
驅動程式可以在其 probe() 回撥中使用此函式,將驅動程式特定資料與介面關聯。
請注意,通常沒有必要清除驅動程式資料指標,即使某些驅動程式出於歷史或特定於實現的原因這樣做。
-
struct usb_interface_cache¶
裝置介面的長期表示
定義:
struct usb_interface_cache {
unsigned num_altsetting;
struct kref ref;
struct usb_host_interface altsetting[];
};
成員
num_altsetting定義的備用設定數量。
ref引用計數器。
altsetting可變長度的介面結構陣列,每個可選擇的備用設定都有一個。 每個都包含一組端點配置。 它們將不按特定順序排列。
描述
這些結構在 usb_device 的生命週期內持續存在,與 struct usb_interface 不同(它僅在其配置已安裝的情況下持續存在)。 可以在任何時候透過這些結構訪問 altsetting 陣列,從而允許比較配置併為 /sys/kernel/debug/usb/devices 偽檔案提供支援。
-
struct usb_host_config¶
裝置配置的表示
定義:
struct usb_host_config {
struct usb_config_descriptor desc;
char *string;
struct usb_interface_assoc_descriptor *intf_assoc[USB_MAXIADS];
struct usb_interface *interface[USB_MAXINTERFACES];
struct usb_interface_cache *intf_cache[USB_MAXINTERFACES];
unsigned char *extra;
int extralen;
};
成員
desc裝置的配置描述符。
string如果存在此配置的 iConfiguration 字串的快取版本,則指向該字串的指標。
intf_assoc此配置中任何介面關聯描述符的列表
interface指向 usb_interface 結構的指標陣列,配置中的每個介面都有一個。 介面數量儲存在 desc.bNumInterfaces 中。 這些指標僅在配置處於活動狀態時有效。
intf_cache指向 usb_interface_cache 結構的指標陣列,配置中的每個介面都有一個。 這些結構在裝置的整個生命週期中都存在。
extra指向包含與此配置關聯的所有額外描述符(在第一個介面描述符之前的那些)的緩衝區的指標。
extralen額外描述符緩衝區的長度。
描述
USB 裝置可能具有多個配置,但一次只能啟用一個配置。 每個配置封裝了不同的操作環境; 例如,雙速裝置將具有單獨的配置,用於全速和高速操作。 可用配置的數量以 bNumConfigurations 的形式儲存在裝置描述符中。
配置可以包含多個介面。 每個介面對應於 USB 裝置的另一種功能,並且只要配置處於活動狀態,所有功能都可用。 USB 標準規定介面應編號從 0 到 desc.bNumInterfaces-1,但許多裝置都弄錯了。 此外,不能保證介面陣列以數字順序排序。 使用 usb_ifnum_to_if() 根據其編號查詢介面條目。
裝置驅動程式不應嘗試啟用配置。 安裝哪個配置的選擇是基於諸如可用電源、提供的功能以及使用者的願望(透過使用者空間工具表達)等考慮因素的策略決策。 但是,驅動程式可以呼叫 usb_reset_configuration() 以重新初始化當前配置及其所有介面。
-
struct usb_device¶
核心對 USB 裝置的表示
定義:
struct usb_device {
int devnum;
char devpath[16];
u32 route;
enum usb_device_state state;
enum usb_device_speed speed;
unsigned int rx_lanes;
unsigned int tx_lanes;
enum usb_ssp_rate ssp_rate;
struct usb_tt *tt;
int ttport;
unsigned int toggle[2];
struct usb_device *parent;
struct usb_bus *bus;
struct usb_host_endpoint ep0;
struct device dev;
struct usb_device_descriptor descriptor;
struct usb_host_bos *bos;
struct usb_host_config *config;
struct usb_host_config *actconfig;
struct usb_host_endpoint *ep_in[16];
struct usb_host_endpoint *ep_out[16];
char **rawdescriptors;
unsigned short bus_mA;
u8 portnum;
u8 level;
u8 devaddr;
unsigned can_submit:1;
unsigned persist_enabled:1;
unsigned reset_in_progress:1;
unsigned have_langid:1;
unsigned authorized:1;
unsigned authenticated:1;
unsigned lpm_capable:1;
unsigned lpm_devinit_allow:1;
unsigned usb2_hw_lpm_capable:1;
unsigned usb2_hw_lpm_besl_capable:1;
unsigned usb2_hw_lpm_enabled:1;
unsigned usb2_hw_lpm_allowed:1;
unsigned usb3_lpm_u1_enabled:1;
unsigned usb3_lpm_u2_enabled:1;
int string_langid;
char *product;
char *manufacturer;
char *serial;
struct list_head filelist;
int maxchild;
u32 quirks;
atomic_t urbnum;
unsigned long active_duration;
unsigned long connect_time;
unsigned do_remote_wakeup:1;
unsigned reset_resume:1;
unsigned port_is_suspended:1;
enum usb_link_tunnel_mode tunnel_mode;
int slot_id;
struct usb2_lpm_parameters l1_params;
struct usb3_lpm_parameters u1_params;
struct usb3_lpm_parameters u2_params;
unsigned lpm_disable_count;
u16 hub_delay;
unsigned use_generic_driver:1;
};
成員
devnum裝置編號; USB 總線上的地址
devpath用於訊息的裝置 ID 字串(例如,/port/...)
route用於 xHCI 的樹拓撲十六進位制字串
state裝置狀態:已配置、未連線等
speed裝置速度:高/全/低(或錯誤)
rx_lanes正在使用的 rx 通道數,USB 3.2 增加了雙通道支援
tx_lanes正在使用的 tx 通道數,USB 3.2 增加了雙通道支援
ssp_rateSuperSpeed Plus phy 信令速率和通道數
tt事務轉換器資訊; 與低/全速裝置、高速集線器一起使用
ttport該 tt 集線器上的裝置埠
toggle每個端點一位,其中 ([0] = IN, [1] = OUT) 端點
parent我們的集線器,除非我們是根
bus我們所屬的匯流排
ep0端點 0 資料(預設控制管道)
dev通用裝置介面
descriptorUSB 裝置描述符
bosUSB 裝置 BOS 描述符集
config裝置的所有配置
actconfig活動配置
ep_inIN 端點陣列
ep_outOUT 端點陣列
rawdescriptors每個配置的原始描述符
bus_mA匯流排提供的當前可用電流
portnum父埠號(原點 1)
levelUSB 集線器祖先的數量
devaddr裝置地址,XHCI:由 HW 分配,其他:與 devnum 相同
can_submit可以提交 URB
persist_enabled為此裝置啟用了 USB_PERSIST
reset_in_progress正在重置裝置
have_langidstring_langid 是否有效
authorized策略說我們可以使用它; (使用者空間)策略確定我們是否授權使用此裝置。 預設情況下,有線 USB 裝置已授權。 WUSB 裝置未授權,直到我們從使用者空間授權它們。 FIXME -- 完整文件
authenticated加密認證透過
lpm_capable裝置支援 LPM
lpm_devinit_allow允許 USB3 裝置發起的 LPM,退出延遲在範圍內
usb2_hw_lpm_capable裝置可以執行 USB2 硬體 LPM
usb2_hw_lpm_besl_capable裝置可以執行 USB2 硬體 BESL LPM
usb2_hw_lpm_enabledUSB2 硬體 LPM 已啟用
usb2_hw_lpm_allowed使用者空間允許啟用 USB 2.0 LPM
usb3_lpm_u1_enabledUSB3 硬體 U1 LPM 已啟用
usb3_lpm_u2_enabledUSB3 硬體 U2 LPM 已啟用
string_langid字串的語言 ID
productiProduct 字串(如果存在)(靜態)
manufactureriManufacturer 字串(如果存在)(靜態)
serialiSerialNumber 字串(如果存在)(靜態)
filelist開啟到此裝置的 usbfs 檔案
maxchild如果為集線器,則埠數
quirks整個裝置的 quirks
urbnum為整個裝置提交的 URB 數量
active_duration裝置未掛起的總時間
connect_time裝置首次連線的時間
do_remote_wakeup應啟用遠端喚醒
reset_resume需要重置而不是恢復
port_is_suspended上游埠已掛起 (L2 或 U3)
tunnel_mode透過 USB4 的連線為原生連線或隧道連線
slot_idxHCI 分配的槽 ID
l1_paramsUSB2 L1 LPM 狀態的最佳努力服務延遲和 L1 超時。
u1_paramsUSB3 U1 LPM 狀態的退出延遲和集線器啟動的超時。
u2_paramsUSB3 U2 LPM 狀態的退出延遲和集線器啟動的超時。
lpm_disable_countusb_disable_lpm() 和 usb_enable_lpm() 使用的引用計數,用於跟蹤需要為此 usb_device 停用 USB 3.0 鏈路電源管理的函式數量。此計數應僅由這些函式操作,並保持 bandwidth_mutex。
hub_delay快取值,包括:parent->hub_delay + wHubDelay + tTPTransmissionDelay (40ns)。將用作 SetIsochDelay 請求的 wValue。
use_generic_driver要求驅動程式核心使用通用驅動程式重新探測。
Notes
Usbcore 驅動程式不應直接設定 usbdev->state。 請改用 usb_set_device_state()。
-
usb_hub_for_each_child¶
usb_hub_for_each_child (hdev, port1, child)
迭代集線器上的所有子裝置
引數
hdev屬於 USB 集線器的 USB 裝置
port1與子裝置關聯的埠號
child子裝置指標
-
int usb_interface_claimed(struct usb_interface *iface)¶
如果聲明瞭介面,則返回 true
引數
struct usb_interface *iface正在檢查的介面
返回
true (非零),如果聲明瞭介面,否則 false (零)。
Note
呼叫者必須擁有驅動程式模型的 usb 匯流排讀鎖。 因此,驅動程式 probe() 條目不需要額外的鎖定,但其他呼叫上下文可能需要顯式宣告該鎖。
-
int usb_make_path(struct usb_device *dev, char *buf, size_t size)¶
返回 usb 樹中的穩定裝置路徑
引數
struct usb_device *dev正在構造其路徑的裝置
char *buf放置字串的位置
size_t size“buf”有多大?
返回
字串的長度 (> 0) 如果大小太小,則為負數。
Note
此識別符號旨在“穩定”,反映硬體中的物理路徑,例如主機控制器或 USB 集線器埠的物理匯流排地址。這使其保持不變,直到透過重新連線 USB 裝置樹或移動 USB 主機控制器來物理重新配置系統為止。新增和刪除裝置(包括主機控制器驅動程式模組中的虛擬根集線器)不會更改這些路徑識別符號;重新啟動或重新列舉也不會。這些是比可更改(“不穩定”)識別符號(例如匯流排編號或裝置地址)更有用的識別符號。
描述
除了連線到 USB 2.0 根集線器的裝置的部分例外情況外,這些識別符號也是可預測的。只要裝置樹未更改,將任何 USB 裝置插入給定的集線器埠始終會為其提供相同的路徑。由於使用了“配套”控制器,因此如果裝置是高速裝置,則連線到 USB 2.0 根集線器(EHCI 主機控制器)埠的裝置將獲得一個路徑 ID,如果是全速或低速裝置,則將獲得另一個路徑 ID。
-
USB_DEVICE¶
USB_DEVICE (vend, prod)
用於描述特定 usb 裝置的宏
-
USB_DEVICE_VER¶
USB_DEVICE_VER (vend, prod, lo, hi)
描述具有版本範圍的特定 usb 裝置
引數
vend16 位 USB 供應商 ID
prod16 位 USB 產品 ID
lobcdDevice_lo 值
hibcdDevice_hi 值
描述
此宏用於建立與具有版本範圍的特定裝置匹配的 struct usb_device_id。
-
USB_DEVICE_INTERFACE_CLASS¶
USB_DEVICE_INTERFACE_CLASS (vend, prod, cl)
描述具有特定介面類的 usb 裝置
引數
vend16 位 USB 供應商 ID
prod16 位 USB 產品 ID
clbInterfaceClass 值
描述
此宏用於建立與裝置的特定介面類匹配的 struct usb_device_id。
-
USB_DEVICE_INTERFACE_PROTOCOL¶
USB_DEVICE_INTERFACE_PROTOCOL (vend, prod, pr)
描述具有特定介面協議的 usb 裝置
引數
vend16 位 USB 供應商 ID
prod16 位 USB 產品 ID
prbInterfaceProtocol 值
描述
此宏用於建立與裝置的特定介面協議匹配的 struct usb_device_id。
-
USB_DEVICE_INTERFACE_NUMBER¶
USB_DEVICE_INTERFACE_NUMBER (vend, prod, num)
描述具有特定介面編號的 usb 裝置
引數
vend16 位 USB 供應商 ID
prod16 位 USB 產品 ID
numbInterfaceNumber 值
描述
此宏用於建立與裝置的特定介面編號匹配的 struct usb_device_id。
-
USB_DEVICE_INFO¶
USB_DEVICE_INFO (cl, sc, pr)
用於描述一類 usb 裝置的宏
引數
clbDeviceClass 值
scbDeviceSubClass 值
prbDeviceProtocol 值
描述
此宏用於建立與特定類別的裝置匹配的 struct usb_device_id。
-
USB_INTERFACE_INFO¶
USB_INTERFACE_INFO (cl, sc, pr)
用於描述一類 usb 介面的宏
引數
clbInterfaceClass 值
scbInterfaceSubClass 值
prbInterfaceProtocol 值
描述
此宏用於建立與特定類別的介面匹配的 struct usb_device_id。
-
USB_DEVICE_AND_INTERFACE_INFO¶
USB_DEVICE_AND_INTERFACE_INFO (vend, prod, cl, sc, pr)
描述具有一類 usb 介面的特定 usb 裝置
引數
vend16 位 USB 供應商 ID
prod16 位 USB 產品 ID
clbInterfaceClass 值
scbInterfaceSubClass 值
prbInterfaceProtocol 值
描述
此宏用於建立與具有特定類別的介面的特定裝置匹配的 struct usb_device_id。
這在顯式匹配具有特定於供應商的 bDeviceClass 值但符合標準的介面的裝置時尤其有用。
-
USB_VENDOR_AND_INTERFACE_INFO¶
USB_VENDOR_AND_INTERFACE_INFO (vend, cl, sc, pr)
描述具有一類 usb 介面的特定 usb 供應商
引數
vend16 位 USB 供應商 ID
clbInterfaceClass 值
scbInterfaceSubClass 值
prbInterfaceProtocol 值
描述
此宏用於建立與具有特定類別的介面的特定供應商匹配的 struct usb_device_id。
這在顯式匹配具有特定於供應商的 bDeviceClass 值但符合標準的介面的裝置時尤其有用。
-
struct usb_driver¶
將 USB 介面驅動程式標識到 usbcore
定義:
struct usb_driver {
const char *name;
int (*probe) (struct usb_interface *intf, const struct usb_device_id *id);
void (*disconnect) (struct usb_interface *intf);
int (*unlocked_ioctl) (struct usb_interface *intf, unsigned int code, void *buf);
int (*suspend) (struct usb_interface *intf, pm_message_t message);
int (*resume) (struct usb_interface *intf);
int (*reset_resume)(struct usb_interface *intf);
int (*pre_reset)(struct usb_interface *intf);
int (*post_reset)(struct usb_interface *intf);
void (*shutdown)(struct usb_interface *intf);
const struct usb_device_id *id_table;
const struct attribute_group **dev_groups;
struct usb_dynids dynids;
struct device_driver driver;
unsigned int no_dynamic_id:1;
unsigned int supports_autosuspend:1;
unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
成員
name驅動程式名稱在 USB 驅動程式中應該是唯一的,並且通常應與模組名稱相同。
probe呼叫以檢視驅動程式是否願意管理裝置上的特定介面。 如果是,probe 返回零並使用
usb_set_intfdata()將驅動程式特定的資料與介面關聯。 它還可以使用usb_set_interface()來指定適當的 altsetting。 如果不願意管理該介面,則返回 -ENODEV;如果發生真正的 IO 錯誤,則返回適當的負 errno 值。disconnect當介面不再可訪問時呼叫,通常是因為其裝置已斷開連線(或正在斷開連線)或正在解除安裝驅動程式模組。
unlocked_ioctl用於想要透過“usbfs”檔案系統與使用者空間通訊的驅動程式。 這使裝置能夠提供將資訊公開給使用者空間的方式,而不管它們是否以其他方式出現在檔案系統中。
suspend當系統因系統休眠或執行時掛起上下文而即將掛起裝置時呼叫。 在系統休眠上下文中,返回值將被忽略,因此如果掛起失敗,請勿嘗試繼續使用該裝置。 而是讓恢復或重置恢復例程從失敗中恢復。
resume當系統正在恢復裝置時呼叫。
reset_resume當掛起的裝置已重置而不是恢復時呼叫。
pre_reset由
usb_reset_device()在裝置即將重置時呼叫。 此例程必須等到驅動程式沒有該裝置的活動 URB,並且在呼叫 post_reset 方法之前不能再提交 URB。post_reset在重置裝置後由
usb_reset_device()呼叫shutdown在關機時呼叫以使裝置靜止。
id_tableUSB 驅動程式使用 ID 表來支援熱插拔。 使用 MODULE_DEVICE_TABLE(usb,...) 匯出此表。 必須設定此表,否則您的驅動程式的探測函式將永遠不會被呼叫。
dev_groups連線到裝置的屬性,一旦裝置繫結到驅動程式,就會建立這些屬性。
dynids在內部用於儲存此驅動程式的動態新增的裝置 ID 列表。
driver驅動程式模型核心驅動程式結構。
no_dynamic_id如果設定為 1,則 USB 核心將不允許透過阻止建立 sysfs 檔案來將動態 ID 新增到此驅動程式。
supports_autosuspend如果設定為 0,則 USB 核心將不允許自動掛起繫結到此驅動程式的介面。
disable_hub_initiated_lpm如果設定為 1,則當發生空閒超時時,USB 核心將不允許集線器啟動較低的功耗鏈路狀態轉換。 仍然允許裝置啟動的 USB 3.0 鏈路 PM。
soft_unbind如果設定為 1,則 USB 核心在呼叫驅動程式的斷開連線方法之前不會終止 URB 和停用端點。
描述
USB 介面驅動程式必須提供名稱、probe() 和 disconnect() 方法以及 id_table。 其他驅動程式欄位是可選的。
id_table 用於熱插拔。 它包含一組描述符,專用資料可以與每個條目關聯。 該表由使用者和核心模式熱插拔支援使用。
probe() 和 disconnect() 方法在可以休眠的上下文中呼叫,但應避免濫用該特權。 連線到裝置的大多數工作應在開啟裝置時完成,並在最後一次關閉時完成撤消。 斷開連線的程式碼需要解決有關 open() 和 close() 方法的併發問題,以及強制所有掛起的 I/O 請求完成(根據需要取消連結它們,並阻止直到取消連結完成)。
-
struct usb_device_driver¶
將 USB 裝置驅動程式標識到 usbcore
定義:
struct usb_device_driver {
const char *name;
bool (*match) (struct usb_device *udev);
int (*probe) (struct usb_device *udev);
void (*disconnect) (struct usb_device *udev);
int (*suspend) (struct usb_device *udev, pm_message_t message);
int (*resume) (struct usb_device *udev, pm_message_t message);
int (*choose_configuration) (struct usb_device *udev);
const struct attribute_group **dev_groups;
struct device_driver driver;
const struct usb_device_id *id_table;
unsigned int supports_autosuspend:1;
unsigned int generic_subclass:1;
};
成員
name驅動程式名稱在 USB 驅動程式中應該是唯一的,並且通常應與模組名稱相同。
match如果已設定,則用於更好的裝置/驅動程式匹配。
probe呼叫以檢視驅動程式是否願意管理特定裝置。 如果是,probe 返回零並使用 dev_set_drvdata() 將驅動程式特定的資料與裝置關聯。 如果不願意管理該裝置,則返回一個負 errno 值。
disconnect當裝置不再可訪問時呼叫,通常是因為它已斷開連線(或正在斷開連線)或驅動程式的模組正在解除安裝。
suspend當系統即將掛起裝置時呼叫。
resume當系統正在恢復裝置時呼叫。
choose_configuration如果為非 NULL,則呼叫此函式來代替預設的 usb_choose_configuration()。 如果此函式返回錯誤,我們將繼續呼叫正常的 usb_choose_configuration()。
dev_groups連線到裝置的屬性,一旦裝置繫結到驅動程式,就會建立這些屬性。
driver驅動程式模型核心驅動程式結構。
id_table與 match() 一起使用,以在 probe() 時選擇更好的匹配驅動程式。
supports_autosuspend如果設定為 0,則 USB 核心將不允許自動掛起繫結到此驅動程式的裝置。
generic_subclass如果設定為 1,則除了驅動程式自己的函式之外,還將呼叫通用 USB 驅動程式的 probe、disconnect、resume 和 suspend 函式,因此不需要複製此設定部分。
描述
USB 驅動程式必須提供上面列出的所有欄位,除了 driver、match 和 id_table。
-
struct usb_class_driver¶
標識想要使用 USB 主編號的 USB 驅動程式
定義:
struct usb_class_driver {
char *name;
char *(*devnode)(const struct device *dev, umode_t *mode);
const struct file_operations *fops;
int minor_base;
};
成員
name此驅動程式的 usb 類裝置名稱。 將顯示在 sysfs 中。
devnode回撥以提供用於建立的可能的裝置節點的命名提示。
fops指向此驅動程式的 struct file_operations 的指標。
minor_base此驅動程式的次要範圍的開始。
描述
此結構用於 usb_register_dev() 和 usb_deregister_dev() 函式,以整合用於它們的許多引數。
-
module_usb_driver¶
module_usb_driver (__usb_driver)
用於註冊 USB 驅動程式的幫助程式宏
引數
__usb_driverusb_driver 結構
描述
用於在模組 init/exit 中不執行任何特殊操作的 USB 驅動程式的幫助程式宏。 這消除了大量樣板程式碼。 每個模組只能使用此宏一次,並且呼叫它會替換 module_init() 和 module_exit()
-
struct urb¶
USB 請求塊
定義:
struct urb {
struct list_head urb_list;
struct list_head anchor_list;
struct usb_anchor *anchor;
struct usb_device *dev;
struct usb_host_endpoint *ep;
unsigned int pipe;
unsigned int stream_id;
int status;
unsigned int transfer_flags;
void *transfer_buffer;
dma_addr_t transfer_dma;
struct scatterlist *sg;
int num_mapped_sgs;
int num_sgs;
u32 transfer_buffer_length;
u32 actual_length;
unsigned char *setup_packet;
dma_addr_t setup_dma;
int start_frame;
int number_of_packets;
int interval;
int error_count;
void *context;
usb_complete_t complete;
struct usb_iso_packet_descriptor iso_frame_desc[];
};
成員
urb_list供 URB 的當前所有者使用。
anchor_list在錨列表中
anchor用於將 URB 錨定到通用繫泊
dev標識要執行請求的 USB 裝置。
ep指向端點的資料結構。 最終將取代 pipe。
pipe儲存端點號、方向、型別等。 使用八個可用的宏建立這些值:usb_{snd,rcv}TYPEpipe(dev,endpoint),其中 TYPE 為“ctrl”(控制)、“bulk”、“int”(中斷)或“iso”(等時)。 例如 usb_sndbulkpipe() 或 usb_rcvintpipe()。 端點號的範圍為零到十五。 請注意,“in”端點 2 與“out”端點 2 是不同的端點(和管道)。 當前配置控制任何給定端點的存在、型別和最大資料包大小。
stream_id批次流的端點流 ID
status這在非 iso 完成函式中讀取,以獲取特定請求的狀態。 ISO 請求僅使用它來判斷 URB 是否已取消連結; 每個幀的詳細狀態都在 iso_frame-desc 的欄位中。
transfer_flags可以使用各種標誌來影響 URB 提交、取消連結或操作的處理方式。 不同型別的 URB 可以使用不同的標誌。
transfer_buffer除非設定了 URB_NO_TRANSFER_DMA_MAP(但即使那時也不要在 transfer_buffer 中留下垃圾),否則這會標識將執行 I/O 請求的(或從中)緩衝區。 此緩衝區必須適合 DMA; 使用
kmalloc()或等效項分配它。 對於傳輸到“in”端點的傳輸,將修改此緩衝區的內容。 此緩衝區用於控制傳輸的資料階段。transfer_dma當 transfer_flags 包括 URB_NO_TRANSFER_DMA_MAP 時,裝置驅動程式表示它提供了此 DMA 地址,主機控制器驅動程式應優先於 transfer_buffer 使用該地址。
sg分散收集緩衝區列表,如果未在“struct usb_bus”中設定 no_sg_constraint,則列表中每個元素(最後一個除外)的緩衝區大小必須可被端點的最大資料包大小整除
num_mapped_sgs(內部)對映的 sg 條目數
num_sgssg 列表中的條目數
transfer_buffer_lengthtransfer_buffer 有多大。 可以根據端點的當前最大資料包大小將傳輸分成多個塊,這是配置的函式,並且編碼在管道中。 當長度為零時,transfer_buffer 和 transfer_dma 都不使用。
actual_length這在非 iso 完成函式中讀取,它告訴傳輸了多少位元組(在 transfer_buffer_length 中)。 除非報告錯誤或執行短讀取,否則它通常與請求的位元組數相同。 URB_SHORT_NOT_OK 傳輸標誌可用於使此類短讀取報告為錯誤。
setup_packet僅用於控制傳輸,這指向八個位元組的設定資料。 控制傳輸始終透過將此資料傳送到裝置來啟動。 然後讀取或寫入 transfer_buffer(如果需要)。
setup_dma設定資料包的 DMA 指標。 呼叫者不得使用此欄位; setup_packet 必須指向有效的緩衝區。
start_frame返回等時傳輸的初始幀。
number_of_packets列出 ISO 傳輸緩衝區的數量。
interval指定中斷或等時傳輸的輪詢間隔。 對於全速和低速裝置,單位為幀(毫秒),對於高速和 SuperSpeed 裝置,單位為微幀(1/8 毫秒)。
error_count返回報告錯誤的 ISO 傳輸的數量。
context用於完成函式。 這通常指向特定於請求的驅動程式上下文。
complete完成處理程式。 此 URB 作為引數傳遞給完成函式。 然後,完成函式可以對 URB 執行任何操作,包括重新提交或釋放它。
iso_frame_desc用於提供 ISO 傳輸緩衝區陣列和收集每個緩衝區的傳輸狀態。
描述
此結構標識 USB 傳輸請求。 URB 必須透過呼叫 usb_alloc_urb() 分配,並透過呼叫 usb_free_urb() 釋放。 可以使用各種 usb_fill_*_urb() 函式完成初始化。 使用 usb_submit_urb() 提交 URB,並且可以使用 usb_unlink_urb() 或 usb_kill_urb() 取消掛起的請求。
Data Transfer Buffers
通常,驅動程式提供使用 kmalloc() 分配的 I/O 緩衝區,或者以其他方式從通用頁面池中獲取的 I/O 緩衝區。 這是由 transfer_buffer 提供的(控制請求也使用 setup_packet),並且主機控制器驅動程式為每個傳輸的緩衝區執行 dma 對映(和取消對映)。 這些對映操作在某些平臺上可能很昂貴(可能使用 dma 緩衝區或與 IOMMU 通訊),但它們在商品 x86 和 ppc 硬體上很便宜。
或者,驅動程式可以傳遞 URB_NO_TRANSFER_DMA_MAP 傳輸標誌,該標誌告訴主機控制器驅動程式,由於裝置驅動程式是 DMA 感知的,因此不需要為 transfer_buffer 進行此類對映。 例如,裝置驅動程式可以使用 usb_alloc_coherent() 分配 DMA 緩衝區,或呼叫 usb_buffer_map()。 當提供此傳輸標誌時,主機控制器驅動程式將嘗試使用在 transfer_dma 欄位中找到的 dma 地址,而不是自己確定 dma 地址。
請注意,如果控制器不支援 DMA(如 hcd_uses_dma() 所示)並且在與根集線器通訊時,仍然必須設定 transfer_buffer。 如果必須在此類控制器上的高記憶體區域和裝置之間傳輸,請建立一個緩衝區或透過錯誤退出。 如果無法設定 transfer_buffer(在高記憶體中)並且控制器具有 DMA 功能,則將其分配為 NULL,以便 usbmon 知道不要使用該值。 必須始終設定 setup_packet,因此它不能位於高記憶體中。
Initialization
所有提交的 URB 都必須初始化 dev、pipe、transfer_flags(可以為零)和 complete 欄位。 所有 URB 還必須初始化 transfer_buffer 和 transfer_buffer_length。 它們可以提供 URB_SHORT_NOT_OK 傳輸標誌,指示應將短讀取視為錯誤; 該標誌對於寫請求無效。
批次 URB 可以使用 URB_ZERO_PACKET 傳輸標誌,指示批次 OUT 傳輸應始終以短資料包終止,即使這意味著新增一個額外的零長度資料包。
控制 URB 必須在 setup_packet 欄位中提供有效指標。 與 transfer_buffer 不同,setup_packet 可能不會預先對映為 DMA。
中斷 URB 必須提供一個 interval,說明輪詢傳輸的頻率(以毫秒為單位,或者對於高速裝置,以 125 微秒為單位)。 提交 URB 後,interval 欄位會反映實際安排傳輸的方式。 輪詢間隔可能比請求的頻率更高。 例如,某些控制器的最大間隔為 32 毫秒,而其他控制器支援高達 1024 毫秒的間隔。 等時 URB 也具有傳輸間隔。 (請注意,對於等時端點以及高速中斷端點,端點描述符中的傳輸間隔編碼是對數的。 裝置驅動程式必須自己將該值轉換為線性單位。)
如果等時端點佇列尚未執行,則主機控制器將安排一個新的 URB 儘快開始,以使頻寬利用率允許。 如果佇列正在執行,則將安排新的 URB 在前一個 URB 結束後緊隨其後的第一個傳輸槽中啟動(如果該槽尚未過期)。 如果該槽已過期(當 IRQ 傳遞延遲很長時間時會發生這種情況),則排程行為取決於 URB_ISO_ASAP 標誌。 如果標誌已清除,則 URB 將被安排在過期的槽中啟動,這意味著它的某些資料包將不會被傳輸; 如果設定了該標誌,則 URB 將被安排在第一個未過期的槽中,從而打破佇列的同步。 完成 URB 後,start_frame 欄位將被設定為安排傳輸的(微)幀號。 幀計數器值的範圍是 HC 特有的,並且範圍從低至 256 到高達 65536 幀。
同步 URB 具有不同的資料傳輸模型,部分原因是服務質量僅為“盡力而為”。呼叫者提供專門分配的 URB,並在末尾包含 number_of_packets 個 iso_frame_desc 結構。每個這樣的資料包都是一個單獨的 ISO 傳輸。同步 URB 通常會被排隊,由驅動程式提交以安排傳輸至少進行雙緩衝,然後在完成處理程式中顯式重新提交,以便資料(如音訊或影片)以主機控制器排程程式可以支援的儘可能恆定的速率傳輸。
完成回撥
完成回撥是在 in_interrupt() 中進行的,完成處理程式應該做的第一件事之一是檢查 status 欄位。status 欄位是為所有 URB 提供的。它用於報告未連結的 URB 以及所有非 ISO 傳輸的狀態。在 URB 返回到完成處理程式之前,不應檢查它。
context 欄位通常用於將 URB 連結回相關的驅動程式或請求狀態。
為非同步 URB 呼叫完成回撥時,actual_length 欄位會告知傳輸了多少位元組。即使 URB 因錯誤而終止或未連結,也會更新此欄位。
ISO 傳輸狀態在 iso_frame_desc 陣列的 status 和 actual_length 欄位中報告,錯誤數量在 error_count 中報告。ISO 傳輸的完成回撥通常會(重新)提交 URB,以確保恆定的傳輸速率。
請注意,即使標記為“public”的欄位,當 urb 由 hcd 擁有時,即從呼叫 usb_submit_urb() 到進入完成例程時,驅動程式也不應觸控它們。
-
void usb_fill_control_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, unsigned char *setup_packet, void *transfer_buffer, int buffer_length, usb_complete_t complete_fn, void *context)¶
初始化控制 urb
引數
struct urb *urb要初始化的 urb 的指標。
struct usb_device *dev此 urb 的
struct usb_device的指標。unsigned int pipe端點管道
unsigned char *setup_packetsetup_packet 緩衝區的指標。該緩衝區必須適合 DMA。
void *transfer_buffer傳輸緩衝區的指標。該緩衝區必須適合 DMA。
int buffer_length傳輸緩衝區的長度
usb_complete_t complete_fnusb_complete_t 函式的指標
void *contexturb 上下文的設定內容。
描述
初始化控制 urb,其中包含將其提交到裝置所需的正確資訊。
傳輸緩衝區和 setup_packet 緩衝區很可能透過 DMA 填充或讀取。獲得可以 DMA 到的緩衝區的最簡單方法是透過 kmalloc() 或同等方法分配它,即使對於非常小的緩衝區也是如此。如果緩衝區嵌入到更大的結構中,則存在緩衝區本身、先前的欄位和/或下一個欄位由於快取不一致而損壞的風險;或者如果它們從快取中逐出,則會減慢速度。有關更多資訊,請檢視 struct urb。
-
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)¶
宏,用於幫助初始化批次 urb
引數
struct urb *urb要初始化的 urb 的指標。
struct usb_device *dev此 urb 的
struct usb_device的指標。unsigned int pipe端點管道
void *transfer_buffer傳輸緩衝區的指標。該緩衝區必須適合 DMA。
int buffer_length傳輸緩衝區的長度
usb_complete_t complete_fnusb_complete_t 函式的指標
void *contexturb 上下文的設定內容。
描述
初始化批次 urb,其中包含將其提交到裝置所需的正確資訊。
有關 transfer_buffer 要求的說明,請參閱 usb_fill_control_urb()。
-
void usb_fill_int_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *transfer_buffer, int buffer_length, usb_complete_t complete_fn, void *context, int interval)¶
宏,用於幫助初始化中斷 urb
引數
struct urb *urb要初始化的 urb 的指標。
struct usb_device *dev此 urb 的
struct usb_device的指標。unsigned int pipe端點管道
void *transfer_buffer傳輸緩衝區的指標。該緩衝區必須適合 DMA。
int buffer_length傳輸緩衝區的長度
usb_complete_t complete_fnusb_complete_t 函式的指標
void *contexturb 上下文的設定內容。
int intervalurb 間隔的設定內容,其編碼方式類似於端點描述符的 bInterval 值。
描述
初始化中斷 urb,其中包含將其提交到裝置所需的正確資訊。
有關 transfer_buffer 要求的說明,請參閱 usb_fill_control_urb()。
請注意,高速和超高速 (+) 中斷端點使用端點間隔的對數編碼,並以微幀(每毫秒八個)而不是幀(每毫秒一個)來表示輪詢間隔。
引數
struct urb *urb要檢查的 URB
返回
如果 urb 描述了 IN 傳輸(裝置到主機),則為 1,否則為 0。
引數
struct urb *urb要檢查的 URB
返回
如果 urb 描述了 OUT 傳輸(主機到裝置),則為 1,否則為 0。
-
struct usb_sg_request¶
對分散/聚集 I/O 的支援
定義:
struct usb_sg_request {
int status;
size_t bytes;
};
成員
status零表示成功,否則為負 errno
位元組計算傳輸的位元組數。
描述
這些請求使用 usb_sg_init() 初始化,然後用作傳遞給 usb_sg_wait() 或 usb_sg_cancel() 的請求控制代碼。請求物件的大多數成員都不供驅動程式訪問。
status 和 bytecount 值僅在 usb_sg_wait() 返回後才有效。如果狀態為零,則 bytecount 與請求的總數匹配。
發生錯誤完成後,驅動程式可能需要清除端點上的停止條件。
USB Core API¶
USB API 中有兩種基本的 I/O 模型。最基本的是非同步:驅動程式以 URB 的形式提交請求,URB 的完成回撥處理下一步。所有 USB 傳輸型別都支援該模型,儘管控制 URB(始終具有設定和狀態階段,但可能沒有資料階段)和同步 URB(允許大資料包幷包括每個資料包的故障報告)都有特殊情況。在此基礎上構建的是同步 API 支援,驅動程式在其中呼叫一個例程,該例程分配一個或多個 URB,提交它們並等待它們完成。有用於單緩衝區控制和批次傳輸的同步包裝器(在某些驅動程式斷開連線的情況下使用起來很尷尬),以及用於基於分散列表的流式 i/o(批次或中斷)的同步包裝器。
USB 驅動程式需要提供可用於 DMA 的緩衝區,儘管它們不一定需要自己提供 DMA 對映。有一些 API 可用於分配 DMA 緩衝區,這可以防止在某些系統上使用反彈緩衝區。在某些情況下,驅動程式可能能夠依靠 64 位 DMA 來消除另一種反彈緩衝區。
引數
struct urb *urb要初始化的 urb 的指標
描述
初始化 urb,以便 USB 子系統可以正確使用它。
如果透過呼叫 usb_alloc_urb() 建立了 urb,則無需呼叫此函式。僅當您自己為 struct urb 分配空間時才使用此函式。如果呼叫此函式,請在釋放 urb 的記憶體時小心,確保 USB core 不再使用它。
僅當您_真的_瞭解自己在做什麼時才使用此函式。
引數
int iso_packets此 urb 的 ISO 資料包數量
gfp_t mem_flags要分配的記憶體型別,有關此型別的有效選項的列表,請參閱
kmalloc()。
描述
建立一個供 USB 驅動程式使用的 urb,初始化一些內部結構,遞增使用計數器,並返回指向它的指標。
如果驅動程式想將此 urb 用於中斷、控制或批次端點,請將“0”作為 ISO 資料包的數量傳遞。
驅動程式完成後必須呼叫 usb_free_urb()。
返回
指向新 urb 的指標,如果記憶體不可用,則為 NULL。
引數
struct urb *urb要釋放的 urb 的指標,可能為 NULL
描述
當 urb 的使用者完成後必須呼叫。當 urb 的最後一個使用者呼叫此函式時,將釋放 urb 的記憶體。
Note
除非設定了 URB_FREE_BUFFER 傳輸標誌,否則與 urb 關聯的傳輸緩衝區不會被釋放。
引數
struct urb *urb要修改的 urb 的指標,可能為 NULL
描述
每當 urb 從裝置驅動程式傳輸到主機控制器驅動程式時,都必須呼叫此函式。這允許為 urb 進行適當的引用計數。
返回
指向引用計數器遞增的 urb 的指標。
引數
struct urb *urb要錨定的 urb 的指標
struct usb_anchor *anchor錨點的指標
描述
可以呼叫此函式來訪問要執行的 URB,而無需費心跟蹤它們
引數
struct urb *urb要錨定的 urb 的指標
描述
呼叫此函式以停止系統跟蹤此 URB
-
int usb_pipe_type_check(struct usb_device *dev, unsigned int pipe)¶
對 USB 裝置的特定管道進行完整性檢查
引數
struct usb_device *dev要檢查的
struct usb_deviceunsigned int pipe要檢查的管道
描述
這會對給定 USB 裝置中的端點執行輕量級完整性檢查。如果管道對特定 USB 裝置有效,則返回 0,否則返回負錯誤程式碼。
引數
const struct urb *urb要檢查的 urb
描述
這會對給定 urb 中的端點執行輕量級完整性檢查。如果 urb 包含有效的端點,則返回 0,否則返回負錯誤程式碼。
引數
struct urb *urb描述請求的 urb 的指標
gfp_t mem_flags要分配的記憶體型別,有關此型別的有效選項的列表,請參閱
kmalloc()。
描述
這會提交傳輸請求,並將描述該請求的 URB 的控制權傳輸到 USB 子系統。稍後將透過呼叫完成處理程式非同步指示請求完成。完成有三種類型:成功、錯誤和取消連結(軟體引起的故障,也稱為“請求取消”)。
可以在中斷上下文中提交 URB。
呼叫者必須在提交 URB 之前正確初始化它。諸如 usb_fill_bulk_urb() 和 usb_fill_control_urb() 之類的函式可用於確保為特定型別的傳輸正確初始化大多數字段,儘管它們不會初始化任何傳輸標誌。
如果提交成功,則來自 URB 的 complete() 回撥將在 USB core 和主機控制器驅動程式 (HCD) 完成 URB 後準確呼叫一次。呼叫完成函式時,URB 的控制權將返回給發出請求的裝置驅動程式。然後,完成處理程式可以立即釋放或重用該 URB。
除了少數例外,在呼叫其 complete() 之前,USB 裝置驅動程式永遠不應訪問由 usbcore 或 HCD 提供的 URB 欄位。這些例外情況與定期傳輸排程有關。對於中斷和同步 urb,作為成功提交 URB 的一部分,修改 urb->interval 以反映使用的實際傳輸週期(通常是 2 個單元的冪)。對於同步 urb,修改 urb->start_frame 以反映 URB 的傳輸計劃何時開始。
並非所有同步傳輸排程策略都有效,但大多數主機控制器驅動程式應輕鬆處理從現在到未來 10-200 毫秒的 ISO 佇列。驅動程式應嘗試在佇列中保留至少一兩個毫秒的資料;許多控制器要求新傳輸在新增到佇列時至少在 1 毫秒的未來開始。如果驅動程式無法跟上並且佇列變空,則新提交的行為由 URB_ISO_ASAP 標誌控制。如果設定了該標誌,或者佇列處於空閒狀態,則始終將 URB 分配給端點計劃中的第一個可用(且尚未過期)插槽。如果未設定該標誌且佇列處於活動狀態,則始終將 URB 分配給計劃中的下一個插槽,該插槽緊跟端點先前 URB 的結尾,即使該插槽在過去也是如此。當以這種方式將資料包分配給已過期的插槽時,該資料包不會被傳輸,並且相應的 usb_iso_packet_descriptor 的 status 欄位將返回 -EXDEV。如果這會發生在 URB 中的所有資料包上,則提交將失敗並顯示 -EXDEV 錯誤程式碼。
對於控制端點,通常使用同步 usb_control_msg() 呼叫(在非中斷上下文中)來代替此呼叫。這通常透過方便的包裝器來使用,用於 USB 2.0 規範中標準化的請求。對於批次端點,可以使用同步 usb_bulk_msg() 呼叫。
請求排隊
可以在先前的 URB 完成之前將它們提交到端點,以最大限度地減少中斷延遲和系統開銷對資料吞吐量的影響。使用此排隊策略,端點的佇列將永遠不會為空。連續同步資料流需要這樣做,某些型別的中斷傳輸也可能需要這樣做。這種排隊還可以透過讓 USB 控制器在驅動程式軟體完成先前(成功)請求的完成處理之前開始處理後續請求,從而最大限度地提高頻寬利用率。
從 Linux 2.6 開始,所有 USB 端點傳輸佇列都支援大於 1 的深度。這以前是 HCD 特定的行為,同步傳輸除外。非同步端點佇列在故障後(傳輸錯誤或取消)的清理期間處於非活動狀態。
預留頻寬傳輸
使用 urb 中指定的間隔重複執行定期傳輸(中斷或同步)。將第一個 urb 提交到端點會預留進行這些傳輸所需的頻寬。如果 USB 子系統無法分配足夠的頻寬來執行定期請求,則提交此類定期請求應會失敗。
對於 xHCI 下的裝置,頻寬在配置時或選擇備用設定時預留。如果沒有足夠的匯流排頻寬,配置/備用設定請求將失敗。因此,由於頻寬限制,提交到 xHCI 下裝置的定期端點永遠不會失敗。
裝置驅動程式必須透過確保某個 URB 始終位於端點的佇列中(可能在完成回撥期間出現短暫的時間除外)來顯式請求重複。當不再有排隊的 urb 時,將取消端點的頻寬預留。這意味著驅動程式可以使用其完成處理程式來確保它們保留所需的頻寬,方法是重新初始化並重新提交剛剛完成的 urb,直到驅動程式不再需要該定期頻寬為止。
記憶體標誌
如何確定使用哪個 mem_flags 的一般規則與 kmalloc 的規則相同。有四種不同的可能值:GFP_KERNEL、GFP_NOFS、GFP_NOIO 和 GFP_ATOMIC。
GFP_NOFS 從未使用過,因為它尚未實現。
- 以下情況使用 GFP_ATOMIC
您位於完成處理程式、中斷、下半部、任務佇列或計時器中,或者
您正在持有自旋鎖或 rwlock(不適用於訊號量),或者
current->state != TASK_RUNNING,只有在您更改它之後才會出現這種情況。
GFP_NOIO 用於儲存裝置的塊 io 路徑和錯誤處理。
所有其他情況都使用 GFP_KERNEL。
- 可以推斷出一些更具體的 mem_flags 規則,例如
網路驅動程式的 start_xmit、timeout 和 receive 方法必須使用 GFP_ATOMIC(在持有自旋鎖的情況下呼叫它們);
scsi 驅動程式的 queuecommand 方法必須使用 GFP_ATOMIC(也在持有自旋鎖的情況下呼叫);
如果將核心執行緒與網路驅動程式一起使用,則必須使用 GFP_NOIO,除非應用 (b) 或 (c);
在完成 down() 操作後,您可以使用 GFP_KERNEL,除非應用 (b) 或 (c) 或您位於儲存驅動程式的塊 io 路徑中;
USB 探測和斷開連線可以使用 GFP_KERNEL,除非應用 (b) 或 (c);並且
在正在執行的儲存或網路裝置上更改韌體使用 GFP_NOIO,除非應用 b) 或 c)
返回
成功提交時為 0。否則為負錯誤號。
引數
struct urb *urb描述先前提交的請求的 urb 的指標,可能為 NULL
描述
此例程會取消正在進行的請求。URB 每次提交僅完成一次,並且每次提交只能取消一次。成功取消意味著 urb 的終止將被加快,並且將使用狀態程式碼呼叫完成處理程式,指示已取消請求(而不是任何其他程式碼)。
驅動程式不應在其斷開連線方法返回後呼叫此例程或相關例程,例如 usb_kill_urb() 或 usb_unlink_anchored_urbs()。斷開連線函式應與驅動程式的 I/O 例程同步,以確保在返回之前所有與 URB 相關的活動都已完成。
此請求是非同步的,但是 HCD 可能會在取消連結期間呼叫 ->complete() 回撥。因此,當驅動程式呼叫 usb_unlink_urb() 時,它們不得持有完成函式可能獲取的任何鎖。成功透過返回 -EINPROGRESS 來指示,此時 URB 可能尚未返回給裝置驅動程式。當最終呼叫它時,完成函式將看到 urb->status == -ECONNRESET。失敗透過 usb_unlink_urb() 返回任何其他值來指示。當 urb 當前未“連結”(即,從未提交、之前已取消連結或硬體已完成它)時,取消連結將失敗,即使尚未執行完成處理程式。
在此例程執行時,不得取消分配 URB。特別是,當驅動程式呼叫此例程時,它必須確保完成處理程式無法取消分配 URB。
取消連結和端點佇列
[下面描述的行為和保證不適用於虛擬根集線器,而僅適用於物理 USB 裝置的端點佇列。]
主機控制器驅動程式 (HCD) 將特定端點的所有 URB 放入佇列中。通常,當控制器硬體處理每個請求時,佇列會前進。但是,當 URB 因錯誤而終止時,其佇列通常會停止(請參見下文),至少在 URB 的完成例程返回之前是這樣。保證停止的佇列不會重新啟動,直到其所有未連結的 URB 都已完全退出,並且其完成例程已執行,即使這要等到原始完成處理程式返回後的某個時間。當 URB 因已取消連結而終止時,也適用相同的行為和保證。
保證批次和中斷端點佇列在 URB 因任何型別的錯誤(包括 -ECONNRESET、-ENOENT 和 -EREMOTEIO)而終止時停止。控制端點佇列的行為方式相同,只是不能保證它們會因 -EREMOTEIO 錯誤而停止。同步端點的佇列的處理方式有所不同,因為它們必須以固定的速率前進。當 URB 遇到錯誤或已取消連結時,此類佇列不會停止。未連結的同步 URB 可能會在資料包流中留下間隙;未定義是否可以填充此類間隙。
請注意,如果且僅當設定了 URB_SHORT_NOT_OK 標誌時,由於收到短資料包而導致的 URB 提前終止才會生成 -EREMOTEIO 錯誤。透過設定此標誌,USB 裝置驅動程式可以為大型或複雜的批次傳輸構建深度佇列,並透過在第一個故障處取消連結所有掛起的 URB,在任何型別的中止傳輸後可靠地清理它們。
當控制 URB 因 -EREMOTEIO 以外的錯誤而終止時,很可能不會發生傳輸的狀態階段。
返回
成功時為 -EINPROGRESS。有關失敗的其他值,請參見描述。
引數
struct urb *urb描述先前提交的請求的 URB 的指標,可能為 NULL
描述
此例程會取消正在進行的請求。保證返回時,所有完成處理程式都將完成,並且 URB 將完全空閒且可重用。這些功能使其成為在 disconnect() 回撥或 close() 函式中停止 I/O 的理想方法。如果請求尚未完成或已取消連結,則完成處理程式將看到 urb->status == -ENOENT。
在該例程執行時,重新提交 URB 的嘗試將失敗並顯示錯誤 -EPERM。因此,即使 URB 的完成處理程式始終嘗試重新提交,它也不會成功,並且 URB 將變為空閒。
在此例程執行時,不得取消分配 URB。特別是,當驅動程式呼叫此例程時,它必須確保完成處理程式無法取消分配 URB。
此例程可能不會在中斷上下文(例如下半部或完成處理程式)中使用,或者在持有自旋鎖時使用,或者在呼叫者無法 schedule() 的其他情況下使用。
驅動程式的斷開連線方法返回後,不應呼叫此例程。
引數
struct urb *urb描述先前提交的請求的 URB 的指標,可能為 NULL
描述
此例程取消正在進行的請求。保證返回時,所有完成處理程式都已完成,並且 URB 將完全空閒且無法重用。這些特性使它成為在 disconnect() 回撥中停止 I/O 的理想方法。如果請求尚未完成或已取消連結,則完成處理程式將看到 urb->status == -ENOENT。
在該例程執行後和執行時,嘗試重新提交 URB 將失敗並出現錯誤 -EPERM。因此,即使 URB 的完成處理程式總是嘗試重新提交,它也不會成功,URB 將變為空閒。
在此例程執行時,不得取消分配 URB。特別是,當驅動程式呼叫此例程時,它必須確保完成處理程式無法取消分配 URB。
此例程可能不會在中斷上下文(例如下半部或完成處理程式)中使用,或者在持有自旋鎖時使用,或者在呼叫者無法 schedule() 的其他情況下使用。
驅動程式的斷開連線方法返回後,不應呼叫此例程。
引數
struct urb *urb要阻止的 URB 的指標,可以為 NULL
描述
在該例程執行後,嘗試重新提交 URB 將失敗並出現錯誤 -EPERM。因此,即使 URB 的完成處理程式總是嘗試重新提交,它也不會成功,URB 將變為空閒。
在此例程執行時,不得取消分配 URB。特別是,當驅動程式呼叫此例程時,它必須確保完成處理程式無法取消分配 URB。
-
void usb_kill_anchored_urbs(struct usb_anchor *anchor)¶
終止與錨關聯的所有 URB
引數
struct usb_anchor *anchor請求繫結到的錨
描述
這會從佇列的末尾開始終止所有未完成的 URB,並保證在此函式返回後,不會從錨發生任何完成回撥。
驅動程式的斷開連線方法返回後,不應呼叫此例程。
-
void usb_poison_anchored_urbs(struct usb_anchor *anchor)¶
停止來自錨的所有流量
引數
struct usb_anchor *anchor請求繫結到的錨
描述
這允許從佇列的末尾開始毒化所有未完成的 URB。新新增的 URB 也將被毒化
驅動程式的斷開連線方法返回後,不應呼叫此例程。
-
void usb_unpoison_anchored_urbs(struct usb_anchor *anchor)¶
讓錨再次成功使用
引數
struct usb_anchor *anchor請求繫結到的錨
描述
反轉 usb_poison_anchored_urbs 的效果,錨可以在它返回後正常使用
-
void usb_unlink_anchored_urbs(struct usb_anchor *anchor)¶
非同步地批次取消傳輸請求
引數
struct usb_anchor *anchor請求繫結到的錨
描述
這允許從佇列的末尾開始取消連結所有未完成的 URB。此函式是非同步的。取消連結只是被觸發。它可能在此函式返回後發生。
驅動程式的斷開連線方法返回後,不應呼叫此例程。
-
void usb_anchor_suspend_wakeups(struct usb_anchor *anchor)¶
引數
struct usb_anchor *anchor您希望在其上暫停喚醒的錨
描述
呼叫此方法可停止從任何 usb_wait_anchor_empty_timeout 等待程式喚醒的最後一個未錨定的 urb。這用於 hcd urb give- back 路徑中,以延遲喚醒,直到完成處理程式執行之後。
-
void usb_anchor_resume_wakeups(struct usb_anchor *anchor)¶
引數
struct usb_anchor *anchor您希望在其上恢復喚醒的錨
描述
允許再次喚醒 usb_wait_anchor_empty_timeout 等待程式,如果錨為空,則喚醒任何當前等待程式。
-
int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, unsigned int timeout)¶
等待錨未使用
引數
struct usb_anchor *anchor您希望變為未使用的錨
unsigned int timeout您願意等待多長時間(以毫秒為單位)
描述
如果您想確保錨的所有 URB 都已完成,請呼叫此方法
返回
如果錨變為未使用,則為非零值。超時時為零。
引數
struct usb_anchor *anchor您想要其 urb 的錨
描述
這將從錨中獲取最舊的 urb,取消錨定並返回它
返回
來自 anchor 的最舊的 urb,如果 anchor 沒有與其關聯的 urb,則為 NULL。
-
void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)¶
取消錨的所有 urb
引數
struct usb_anchor *anchor您想要取消錨定的 urb 的錨
描述
使用此方法擺脫錨的所有 urb
-
int usb_anchor_empty(struct usb_anchor *anchor)¶
錨是否為空
引數
struct usb_anchor *anchor您要查詢的錨
返回
如果錨沒有與其關聯的 urb,則為 1。
-
int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout)¶
構建一個控制 urb,將其傳送出去並等待完成
引數
struct usb_device *dev指向要將訊息傳送到的 usb 裝置的指標
unsigned int pipe要將訊息傳送到的端點“管道”
__u8 requestUSB 訊息請求值
__u8 requesttypeUSB 訊息請求型別值
__u16 valueUSB 訊息值
__u16 indexUSB 訊息索引值
void *data指向要傳送的資料的指標
__u16 size要傳送的資料的長度(以位元組為單位)
int timeout在超時之前等待訊息完成的時間(以毫秒為單位)(如果為 0,則永遠等待)
上下文
任務上下文,可能會睡眠。
描述
此函式將一個簡單的控制訊息傳送到指定的端點,並等待訊息完成或超時。
不要從中斷上下文中使用此函式。如果您需要非同步訊息,或者需要從中斷上下文中傳送訊息,請使用 usb_submit_urb()。如果您的驅動程式中的執行緒使用此呼叫,請確保您的 disconnect() 方法可以等待它完成。由於您沒有使用 URB 的控制代碼,因此無法取消請求。
返回
如果成功,則為傳輸的位元組數。否則,為負錯誤號。
-
int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request, __u8 requesttype, __u16 value, __u16 index, const void *driver_data, __u16 size, int timeout, gfp_t memflags)¶
構建一個控制“傳送”訊息,將其傳送出去並等待完成
引數
struct usb_device *dev指向要將訊息傳送到的 usb 裝置的指標
__u8 endpoint要將訊息傳送到的端點
__u8 requestUSB 訊息請求值
__u8 requesttypeUSB 訊息請求型別值
__u16 valueUSB 訊息值
__u16 indexUSB 訊息索引值
const void *driver_data指向要傳送的資料的指標
__u16 size要傳送的資料的長度(以位元組為單位)
int timeout在超時之前等待訊息完成的時間(以毫秒為單位)(如果為 0,則永遠等待)
gfp_t memflags用於緩衝區記憶體分配的標誌
上下文
!in_interrupt ()
描述
此函式將一個控制訊息傳送到指定的端點,該端點不應填寫響應(即“傳送訊息”),並等待訊息完成或超時。
不要從中斷上下文中使用此函式。如果您需要非同步訊息,或者需要從中斷上下文中傳送訊息,請使用 usb_submit_urb()。如果您的驅動程式中的執行緒使用此呼叫,請確保您的 disconnect() 方法可以等待它完成。由於您沒有使用 URB 的控制代碼,因此無法取消請求。
資料指標可以引用堆疊上的某個位置或任何其他位置,因為它根本不會被修改。這沒有 usb_control_msg() 的限制,後者的資料指標必須指向動態分配的記憶體(即可以成功 DMA 到裝置的記憶體)。
返回
如果成功,則返回 0。否則,返回一個負錯誤號。
-
int usb_control_msg_recv(struct usb_device *dev, __u8 endpoint, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *driver_data, __u16 size, int timeout, gfp_t memflags)¶
構建一個控制“接收”訊息,將其傳送出去並等待完成
引數
struct usb_device *dev指向要將訊息傳送到的 usb 裝置的指標
__u8 endpoint要將訊息傳送到的端點
__u8 requestUSB 訊息請求值
__u8 requesttypeUSB 訊息請求型別值
__u16 valueUSB 訊息值
__u16 indexUSB 訊息索引值
void *driver_data指向要由訊息填充的資料的指標
__u16 size要接收的資料的長度(以位元組為單位)
int timeout在超時之前等待訊息完成的時間(以毫秒為單位)(如果為 0,則永遠等待)
gfp_t memflags用於緩衝區記憶體分配的標誌
上下文
!in_interrupt ()
描述
此函式將一個控制訊息傳送到指定的端點,該端點應填寫響應(即“接收訊息”),並等待訊息完成或超時。
不要從中斷上下文中使用此函式。如果您需要非同步訊息,或者需要從中斷上下文中傳送訊息,請使用 usb_submit_urb()。如果您的驅動程式中的執行緒使用此呼叫,請確保您的 disconnect() 方法可以等待它完成。由於您沒有使用 URB 的控制代碼,因此無法取消請求。
資料指標可以引用堆疊上的某個位置或任何其他可以成功寫入的位置。此函式沒有 usb_control_msg() 的限制,後者的資料指標必須指向動態分配的記憶體(即可以成功 DMA 到裝置的記憶體)。
為了使此函式成功,“整個”訊息必須從裝置正確接收。如果裝置返回的資料量少於預期,則該函式將失敗。不要將其用於可能返回可變資料量的訊息。
返回
如果成功,則返回 0。否則,返回一個負錯誤號。
-
int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)¶
構建一箇中斷 urb,將其傳送出去並等待完成
引數
struct usb_device *usb_dev指向要將訊息傳送到的 usb 裝置的指標
unsigned int pipe要將訊息傳送到的端點“管道”
void *data指向要傳送的資料的指標
int len要傳送的資料的長度(以位元組為單位)
int *actual_length指向用於放置以位元組為單位的實際傳輸長度的位置的指標
int timeout在超時之前等待訊息完成的時間(以毫秒為單位)(如果為 0,則永遠等待)
上下文
任務上下文,可能會睡眠。
描述
此函式將一個簡單的中斷訊息傳送到指定的端點,並等待訊息完成或超時。
不要從中斷上下文中使用此函式。如果您需要非同步訊息,或者需要從中斷上下文中傳送訊息,請使用 usb_submit_urb() 如果您的驅動程式中的執行緒使用此呼叫,請確保您的 disconnect() 方法可以等待它完成。由於您沒有使用 URB 的控制代碼,因此無法取消請求。
返回
如果成功,則為 0。否則,為負錯誤號。實際傳輸的位元組數將儲存在 actual_length 引數中。
-
int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)¶
構建一個批次 urb,將其傳送出去並等待完成
引數
struct usb_device *usb_dev指向要將訊息傳送到的 usb 裝置的指標
unsigned int pipe要將訊息傳送到的端點“管道”
void *data指向要傳送的資料的指標
int len要傳送的資料的長度(以位元組為單位)
int *actual_length指向用於放置以位元組為單位的實際傳輸長度的位置的指標
int timeout在超時之前等待訊息完成的時間(以毫秒為單位)(如果為 0,則永遠等待)
上下文
任務上下文,可能會睡眠。
描述
此函式將一個簡單的批次訊息傳送到指定的端點,並等待訊息完成或超時。
不要從中斷上下文中使用此函式。如果您需要非同步訊息,或者需要從中斷上下文中傳送訊息,請使用 usb_submit_urb() 如果您的驅動程式中的執行緒使用此呼叫,請確保您的 disconnect() 方法可以等待它完成。由於您沒有使用 URB 的控制代碼,因此無法取消請求。
由於沒有 usb_interrupt_msg() 並且沒有 USBDEVFS_INTERRUPT ioctl,使用者被迫濫用此例程,透過使用它來提交中斷端點的 URB。如果目標是中斷端點,我們將自由地建立一箇中斷 URB(具有預設間隔)。
返回
如果成功,則為 0。否則,為負錯誤號。實際傳輸的位元組數將儲存在 actual_length 引數中。
-
int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, unsigned pipe, unsigned period, struct scatterlist *sg, int nents, size_t length, gfp_t mem_flags)¶
初始化基於散列表的批次/中斷 I/O 請求
引數
struct usb_sg_request *io正在初始化的請求塊。在
usb_sg_wait()返回之前,將其視為指向不透明記憶體塊的指標。struct usb_device *dev將傳送或接收資料的 usb 裝置
unsigned pipe用於傳輸資料的端點“管道”
unsigned period中斷端點的輪詢速率,以幀或(對於高速端點)微幀為單位;對於批次被忽略
struct scatterlist *sg散列表條目
int nents散列表中有多少個條目
size_t length要從散列表中傳送多少位元組,或傳送列表中標識的每個位元組為零。
gfp_t mem_flags影響此呼叫中記憶體分配的 SLAB_* 標誌
描述
這將初始化一個分散/聚集請求,分配資源,如 I/O 對映和 urb 記憶體(除了 USB 控制器驅動程式可能使用的記憶體)。
必須使用 usb_sg_wait() 發出請求,它會等待 I/O 完成(或被取消),然後清除由 usb_sg_init() 分配的所有資源。
可以使用 usb_sg_cancel() 取消請求,可以在呼叫 usb_sg_wait() 之前或之後進行。
返回
成功為零,否則為負 errno 值。
-
void usb_sg_wait(struct usb_sg_request *io)¶
同步執行散佈/聚集請求
引數
struct usb_sg_request *io請求塊控制代碼,使用
usb_sg_init()初始化。當此呼叫返回時,某些欄位變得可訪問。
上下文
任務上下文,可能會睡眠。
描述
此函式會阻塞,直到指定的 I/O 操作完成。它利用相關 I/O 請求的分組來獲得良好的傳輸速率,方法是將請求排隊。在更高的速度下,這種排隊可以顯著提高 USB 吞吐量。
此函式有三種完成型別。
成功,其中 io->status 為零。傳輸的 io->bytes 數與請求的相同。
錯誤,其中 io->status 為負 errno 值。錯誤之前傳輸的 io->bytes 數通常小於請求的數,並且可以為非零值。
取消,一種錯誤,狀態為 -ECONNRESET,由
usb_sg_cancel()啟動。
當此函式返回時,透過 usb_sg_init() 或此呼叫分配的所有記憶體都將被釋放。請求塊引數仍然可以傳遞給 usb_sg_cancel(),或者可以釋放它。它也可以重新初始化然後重複使用。
資料傳輸速率
批次傳輸對於全速或高速端點有效。最佳全速資料速率是每幀 19 個數據包,每個資料包 64 位元組,或每毫秒 1216 位元組。最佳高速資料速率是每微幀 13 個數據包,每個資料包 512 位元組,或每毫秒 52 KBytes。
透過此 API 使用中斷傳輸的原因很可能是為了保留高速頻寬,在這種情況下,可以傳輸高達每毫秒 24 KBytes 的資料。對於低速或全速中斷端點,此功能不太有用,這些端點最多允許每毫秒一個數據包,最大為 8 或 64 位元組(分別)。
沒有必要呼叫此函式來為 xHCI 主機控制器下的裝置保留頻寬,因為頻寬是在選擇配置或介面備用設定時保留的。
-
void usb_sg_cancel(struct usb_sg_request *io)¶
停止由
usb_sg_wait()發出的散佈/聚集 i/o
引數
struct usb_sg_request *io請求塊,使用
usb_sg_init()初始化
描述
這會在由 usb_sg_wait() 啟動後停止請求。它還可以防止由 usb_sg_init() 初始化的請求啟動,因此該呼叫只是釋放分配給請求的資源。
-
int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)¶
發出通用的 GET_DESCRIPTOR 請求
引數
struct usb_device *dev正在檢索其描述符的裝置
unsigned char type描述符型別 (USB_DT_*)
unsigned char index描述符的編號
void *buf將描述符放在哪裡
int size“buf”有多大?
上下文
任務上下文,可能會睡眠。
描述
獲取 USB 描述符。存在方便函式,可以簡化某些型別的描述符的獲取。使用 usb_get_string() 或 usb_string() 用於 USB_DT_STRING。裝置 (USB_DT_DEVICE) 和配置描述符 (USB_DT_CONFIG) 是裝置結構的一部分。除了許多 USB 標準描述符外,一些裝置還使用特定於類或特定於供應商的描述符。
此呼叫是同步的,不能在中斷上下文中使用。
返回
成功時接收到的位元組數,否則為底層 usb_control_msg() 呼叫返回的狀態程式碼。
-
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)¶
返回字串描述符的 UTF-8 版本
引數
struct usb_device *dev正在檢索其字串描述符的裝置
int index描述符的編號
char *buf放置字串的位置
size_t size“buf”有多大?
上下文
任務上下文,可能會睡眠。
描述
這會將裝置返回的 UTF-16LE 編碼的字串(來自 usb_get_string_descriptor())轉換為大多數核心上下文中更常用的以 null 結尾的 UTF-8 編碼的字串。請注意,此函式會選擇裝置支援的第一種語言的字串。
此呼叫是同步的,不能在中斷上下文中使用。
返回
字串的長度 (>= 0) 或 usb_control_msg 狀態 (< 0)。
-
char *usb_cache_string(struct usb_device *udev, int index)¶
讀取字串描述符並將其快取以供以後使用
引數
struct usb_device *udev正在讀取其字串描述符的裝置
int index描述符索引
返回
指向包含描述符字串的 kmalloc'ed 緩衝區的指標,如果索引為 0 或無法讀取字串,則為 NULL。
-
int usb_get_status(struct usb_device *dev, int recip, int type, int target, void *data)¶
發出一個 GET_STATUS 呼叫
引數
struct usb_device *dev正在檢查狀態的裝置
int recipUSB_RECIP_*;用於裝置、介面或端點
int typeUSB_STATUS_TYPE_*;用於標準或 PTM 狀態型別
int target零(用於裝置),否則為介面或端點號
void *data指向兩個位元組的點陣圖資料的指標
上下文
任務上下文,可能會睡眠。
描述
返回裝置、介面或端點狀態。通常只用於檢視裝置是否為自供電,或者是否啟用了遠端喚醒功能;或者批次或中斷端點是否已停止(“stalled”)。
這些狀態點陣圖中的位使用 SET_FEATURE 請求設定,並使用 CLEAR_FEATURE 請求清除。 usb_clear_halt() 函式應用於清除停止(“stall”)狀態。
此呼叫是同步的,不能在中斷上下文中使用。
成功時返回 0 和 *data 中的狀態值(以主機位元組順序),否則返回底層 usb_control_msg() 呼叫的狀態程式碼。
-
int usb_clear_halt(struct usb_device *dev, int pipe)¶
告訴裝置清除端點停止/停頓狀態
引數
struct usb_device *dev端點已停止的裝置
int pipe正在清除的端點“管道”
上下文
任務上下文,可能會睡眠。
描述
這用於清除批次和中斷端點的停止狀態,如 URB 完成狀態報告的那樣。停止的端點有時被稱為“stalled”。在清除停止狀態之前,此類端點無法傳送或接收資料。任何為此類端點排隊的 URB 通常應在清除停止狀態之前由驅動程式取消連結,如 USB 2.0 規範的 5.7.5 和 5.8.5 節中所述。
請注意,控制和同步端點不會停止,儘管控制端點使用相同的狀態程式碼報告“協議停頓”(對於不支援的請求),該狀態程式碼用於報告真正的停頓。
此呼叫是同步的,不能在中斷上下文中使用。如果驅動程式中的執行緒使用此呼叫,請確保 disconnect() 方法可以等待它完成。
返回
成功時返回零,否則返回底層 usb_control_msg() 呼叫返回的狀態程式碼。
-
void usb_reset_endpoint(struct usb_device *dev, unsigned int epaddr)¶
重置端點的狀態。
引數
struct usb_device *dev要重置端點的裝置
unsigned int epaddr端點的地址。輸出的端點號,輸入的端點號 + USB_DIR_IN
描述
重置任何主機端端點狀態,例如切換位、序列號或當前視窗。
-
int usb_set_interface(struct usb_device *dev, int interface, int alternate)¶
使特定的備用設定成為當前設定
引數
struct usb_device *dev正在更新其介面的裝置
int interface正在更新的介面
int alternate正在選擇的設定。
上下文
任務上下文,可能會睡眠。
描述
這用於啟用預設情況下可能未啟用的介面上的資料傳輸。並非所有裝置都支援此類可配置性。只有繫結到介面的驅動程式才能更改其設定。
在任何給定的配置中,每個介面可以有多個備用設定。這些通常用於控制頻寬消耗級別。例如,高速中斷端點的預設設定可能每微幀傳送不超過 64 個位元組,而每微幀最多 3KBytes 的中斷傳輸是合法的。此外,同步端點可能永遠不會成為介面預設設定的一部分。要訪問此類頻寬,必須使備用介面設定成為當前設定。
請注意,在 Linux USB 子系統中,與給定備用設定中端點關聯的頻寬只有在提交需要該頻寬的 URB 時才會被保留。某些其他作業系統會在選擇配置時提前分配頻寬。
xHCI 在 usb_hcd_alloc_bandwidth() 中保留頻寬並配置備用設定。如果失敗,原始介面備用設定可能會被停用。驅動程式不能依賴於失敗後生效的任何特定備用設定。
此呼叫是同步的,不能在中斷上下文中使用。此外,驅動程式不得在為該介面中的端點計劃 urbs 時更改備用設定;所有此類 urbs 必須首先完成(可能透過取消連結強制執行)。如果驅動程式中的執行緒使用此呼叫,請確保 disconnect() 方法可以等待它完成。
返回
成功時返回零,否則返回底層 usb_control_msg() 呼叫返回的狀態程式碼。
-
int usb_reset_configuration(struct usb_device *dev)¶
輕量級裝置重置
引數
struct usb_device *dev正在重置其配置的裝置
描述
這使用當前配置向裝置發出標準 SET_CONFIGURATION 請求。效果是重置裝置中的大多數 USB 相關狀態,包括介面備用設定(重置為零)、端點停止(清除)和端點狀態(僅適用於批次和中斷端點)。其他 usbcore 狀態保持不變,包括 usb 裝置驅動程式與介面的繫結。
由於這會影響多個介面,因此請避免將此與複合(多介面)裝置一起使用。相反,每個介面的驅動程式可以在其宣告的介面上使用 usb_set_interface()。但請注意;某些裝置不支援 SET_INTERFACE 請求,其他裝置不會重置所有介面狀態(特別是端點狀態)。重置整個配置會影響其他驅動程式的介面。
呼叫者必須擁有裝置鎖。
如果此例程失敗,裝置可能處於無法使用的狀態,其中端點已停用,介面僅部分啟用。
返回
成功時返回零,否則返回負錯誤程式碼。
-
int usb_set_wireless_status(struct usb_interface *iface, enum usb_wireless_status status)¶
設定 wireless_status 結構成員
引數
struct usb_interface *iface要修改的介面
enum usb_wireless_status status新的無線狀態
描述
將 wireless_status 結構成員設定為新值,並根據需要發出 sysfs 更改。
返回
成功時返回 0,如果已設定則返回 -EALREADY。
-
int usb_driver_set_configuration(struct usb_device *udev, int config)¶
為驅動程式提供一種更改裝置配置的方法
引數
struct usb_device *udev正在更新其配置的裝置
int config正在選擇的配置。
上下文
在程序上下文中,必須能夠休眠
描述
裝置介面驅動程式不允許更改裝置配置。這是因為更改配置將破壞驅動程式繫結的介面並建立新介面;這就像軟盤驅動程式告訴計算機用磁帶驅動器替換軟盤驅動器一樣!
儘管如此,在某些特殊情況下,可能會出現這種需求。此例程透過使用工作執行緒提交 change-config 請求來繞過正常限制。
返回
如果請求已成功排隊,則返回 0,否則返回錯誤程式碼。呼叫者無法知道排隊的請求最終是否會成功。
-
int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, struct usb_interface *intf, u8 *buffer, int buflen)¶
解析 CDC 裝置中存在的額外標頭
引數
struct usb_cdc_parsed_header *hdr放置解析結果的位置
struct usb_interface *intf請求解析的介面
u8 *buffer指向要解析的額外標頭的指標
int buflen額外標頭的長度
描述
這會評估 CDC 裝置中存在的額外標頭,這些標頭綁定了資料和控制的介面,並提供有關裝置功能的詳細資訊。
返回
解析的描述符數或 -EINVAL(如果標頭存在無法挽救的矛盾)
-
int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver)¶
註冊 USB 裝置,並請求一個次裝置號
引數
struct usb_interface *intf指向正在註冊的 usb_interface 的指標
struct usb_class_driver *class_driver指向此裝置的 usb_class_driver 的指標
描述
所有使用 USB 主裝置號的 USB 驅動程式都應呼叫此函式。如果啟用了 CONFIG_USB_DYNAMIC_MINORS,則將從可用次裝置號列表中動態分配次裝置號。如果未啟用,則次裝置號將基於下一個可用的空閒次裝置號,從 class_driver->minor_base 開始。
此函式還在 sysfs 樹中建立一個 USB 類裝置。
當驅動程式完成此函式給出的次裝置號時,必須呼叫 usb_deregister_dev()。
返回
-EINVAL 如果嘗試註冊裝置時發生錯誤,成功時返回 0。
-
void usb_deregister_dev(struct usb_interface *intf, struct usb_class_driver *class_driver)¶
登出 USB 裝置的動態次裝置號。
引數
struct usb_interface *intf指向正在登出的 usb_interface 的指標
struct usb_class_driver *class_driver指向此裝置的 usb_class_driver 的指標
描述
與 usb_register_dev() 結合使用。當 USB 驅動程式完成從 usb_register_dev() 呼叫獲得的次裝置號時(通常是當裝置與系統斷開連線時),會呼叫此函式。
此函式還會從 sysfs 樹中刪除 USB 類裝置。
所有使用 USB 主裝置號的驅動程式都應呼叫此函式。
-
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *data)¶
將驅動程式繫結到介面
引數
struct usb_driver *driver要繫結的驅動程式
struct usb_interface *iface要繫結到的介面;必須位於 USB 裝置的活動配置中
void *data與該介面關聯的驅動程式資料
描述
當 USB 裝置驅動程式在探測時需要宣告裝置上的多個介面時(當前音訊和 acm 是示例),會使用此函式。任何裝置驅動程式都不應直接修改內部 usb_interface 或 usb_device 結構成員。
呼叫者必須擁有裝置鎖,因此驅動程式 probe() 條目不需要額外的鎖定,但其他呼叫上下文可能需要顯式宣告該鎖。
返回
成功時返回 0。
-
void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)¶
從介面解除繫結驅動程式
引數
struct usb_driver *driver要解除繫結的驅動程式
struct usb_interface *iface要解除繫結的介面
描述
驅動程式可以使用此函式來釋放介面,而無需等待呼叫其 disconnect() 方法。在典型情況下,這也會導致呼叫驅動程式的 disconnect() 方法。
此呼叫是同步的,不能在中斷上下文中使用。呼叫者必須擁有裝置鎖,因此驅動程式 disconnect() 條目不需要額外的鎖定,但其他呼叫上下文可能需要顯式宣告該鎖。
-
const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)¶
查詢第一個與裝置或介面匹配的 usb_device_id
引數
struct usb_interface *interface感興趣的介面
const struct usb_device_id *idusb_device_id 結構陣列,以零條目結尾
描述
usb_match_id 搜尋 usb_device_id 陣列,並返回第一個與裝置或介面匹配的 usb_device_id,否則返回 null。這用於將驅動程式繫結(或重新繫結)到介面。大多數 USB 裝置驅動程式會透過 USB 核心間接使用它,但某些分層驅動程式框架會直接使用它。這些裝置表透過 modutils 與 MODULE_DEVICE_TABLE 一起匯出,以支援 USB 熱插拔的驅動程式載入功能。
匹配什麼
usb_device_id 中的“match_flags”元素控制使用哪些成員。如果設定了相應的位,則 device_id 中的值必須與其在裝置或介面描述符中的相應成員匹配,否則 device_id 不匹配。
“driver_info”通常僅由裝置驅動程式使用,但如果您提供僅具有非零“driver_info”欄位的 id,則可以建立萬用字元“匹配任何內容”usb_device_id 作為驅動程式的“modules.usbmap”條目。如果您這樣做,USB 裝置驅動程式的 probe() 例程應使用額外的智慧來決定是否繫結到指定的介面。
什麼使良好的 usb_device_id 表
匹配演算法非常簡單,因此驅動程式選擇中的智慧必須來自智慧驅動程式 id 記錄。除非您有充分的理由使用其他選擇策略,否則僅在相關組中提供匹配元素,並按從特定到一般的順序排列匹配說明符。如果可以,請使用為此目的提供的宏。
最具體的匹配說明符使用裝置描述符資料。這些通常與特定於產品的匹配一起使用;USB_DEVICE 宏允許您提供供應商和產品 ID,並且您還可以匹配產品修訂範圍。這些廣泛用於具有特定於應用程式或供應商的 bDeviceClass 值的裝置。
基於裝置類/子類/協議規範的匹配稍微通用一些;使用 USB_DEVICE_INFO 宏或其同級宏。這些與 bDeviceClass 未指定每個介面都有其自己的類的單功能裝置一起使用。
基於介面類/子類/協議的匹配是最通用的;它們允許驅動程式繫結到多功能裝置上的任何介面。使用 USB_INTERFACE_INFO 宏或其同級宏來匹配每個介面類樣式的裝置(如 bInterfaceClass 中記錄的那樣)。
請注意,如果裝置類設定為 Vendor-Specific,則由 USB_INTERFACE_INFO 建立的條目將不匹配任何介面。這是故意的;根據 USB 規範,這些裝置的介面類/子類/協議的含義也是特定於供應商的,因此匹配標準產品類無論如何都行不通。如果您真的想對此類裝置使用基於介面的匹配,請建立一個也指定供應商 ID 的匹配記錄。(不幸的是,沒有用於建立此類記錄的標準宏。)
在這些組中,請記住並非所有組合都有意義。例如,不要提供沒有供應商和產品 ID 的產品版本範圍;或者指定沒有其關聯的類和子類的協議。
返回
第一個匹配的 usb_device_id 或 NULL。
-
int usb_register_device_driver(struct usb_device_driver *new_udriver, struct module *owner)¶
註冊 USB 裝置(非介面)驅動程式
引數
struct usb_device_driver *new_udriver裝置驅動程式的 USB 操作
struct module *owner此驅動程式的模組所有者。
描述
向 USB 核心註冊 USB 裝置驅動程式。每當新增新驅動程式時,都會重新掃描未連線裝置的列表,從而允許新驅動程式連線到任何識別的裝置。
返回
失敗時返回負錯誤程式碼,成功時返回 0。
-
void usb_deregister_device_driver(struct usb_device_driver *udriver)¶
登出 USB 裝置(非介面)驅動程式
引數
struct usb_device_driver *udriver要登出的裝置驅動程式的 USB 操作
上下文
必須能夠休眠
描述
從內部 USB 驅動程式列表中取消連結指定的驅動程式。
-
int usb_register_driver(struct usb_driver *new_driver, struct module *owner, const char *mod_name)¶
註冊 USB 介面驅動程式
引數
struct usb_driver *new_driver介面驅動程式的 USB 操作
struct module *owner此驅動程式的模組所有者。
const char *mod_name模組名稱字串
描述
向 USB 核心註冊 USB 介面驅動程式。每當新增新驅動程式時,都會重新掃描未連線介面的列表,從而允許新驅動程式連線到任何識別的介面。
返回
失敗時返回負錯誤程式碼,成功時返回 0。
注意
如果您希望驅動程式使用 USB 主裝置號,則必須呼叫 usb_register_dev() 以啟用該功能。此函式不再處理該功能。
-
void usb_deregister(struct usb_driver *driver)¶
登出 USB 介面驅動程式
引數
struct usb_driver *driver要登出的介面驅動程式的 USB 操作
上下文
必須能夠休眠
描述
從內部 USB 驅動程式列表中取消連結指定的驅動程式。
注意
如果您呼叫了 usb_register_dev(),您仍然需要呼叫 usb_deregister_dev() 以清理驅動程式的已分配次裝置號,此 * 呼叫將不再為您執行此操作。
-
void usb_enable_autosuspend(struct usb_device *udev)¶
允許 USB 裝置自動掛起
引數
struct usb_device *udev可能自動掛起的 USB 裝置
描述
此例程允許 udev 自動掛起。自動掛起只有在 autosuspend_delay 過去且滿足所有其他必要條件後才會發生。
呼叫者必須持有 udev 的裝置鎖。
-
void usb_disable_autosuspend(struct usb_device *udev)¶
防止 USB 裝置自動掛起
引數
struct usb_device *udev可能不會自動掛起的 USB 裝置
描述
此例程阻止 udev 自動掛起,如果已經自動掛起,則將其喚醒。
呼叫者必須持有 udev 的裝置鎖。
-
void usb_autopm_put_interface(struct usb_interface *intf)¶
減少 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該減少計數器的 usb_interface
描述
當介面驅動程式完成使用 intf 並希望允許其自動掛起時,應呼叫此例程。一個典型的例子是字元裝置驅動程式在其裝置檔案關閉時。
該例程會減少 intf 的使用計數器。當計數器達到 0 時,將嘗試對 intf 的裝置進行延遲自動掛起請求。嘗試可能會失敗(參見 autosuspend_check())。
此例程只能在程序上下文中執行。
-
void usb_autopm_put_interface_async(struct usb_interface *intf)¶
減少 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該減少計數器的 usb_interface
描述
此例程的功能與 usb_autopm_put_interface() 非常相似:它減少 intf 的使用計數器,如果計數器 <= 0,則計劃一個延遲自動掛起請求。區別在於它不執行任何同步;呼叫者應持有私有鎖並自行處理所有同步問題。
通常,如果沒有更多 URB 掛起,驅動程式會在 URB 的完成處理程式中呼叫此例程。
此例程可以在原子上下文中執行。
-
void usb_autopm_put_interface_no_suspend(struct usb_interface *intf)¶
減少 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該減少計數器的 usb_interface
描述
此例程減少 intf 的使用計數器,但不執行自動掛起。
此例程可以在原子上下文中執行。
-
int usb_autopm_get_interface(struct usb_interface *intf)¶
增加 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該增加計數器的 usb_interface
描述
當介面驅動程式想要使用 intf 並需要保證它沒有掛起時,應呼叫此例程。此外,該例程還會阻止 intf 隨後被自動掛起。(請注意,這不會阻止源自 PM 核心的掛起事件。)此阻止將持續到呼叫 usb_autopm_put_interface() 或取消繫結 intf。一個典型的例子是字元裝置驅動程式在其裝置檔案開啟時。
intf 的使用計數器會增加以防止隨後的自動掛起。但是,如果自動恢復失敗,則計數器會重新減少。
此例程只能在程序上下文中執行。
返回
成功時返回 0。
-
int usb_autopm_get_interface_async(struct usb_interface *intf)¶
增加 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該增加計數器的 usb_interface
描述
此例程的功能與 usb_autopm_get_interface() 非常相似:它增加 intf 的使用計數器,如果裝置已掛起,則將自動恢復請求排隊。區別在於它不執行任何同步(呼叫者應持有私有鎖並自行處理所有同步問題),並且它不直接自動恢復裝置(它僅將請求排隊)。成功呼叫後,裝置可能尚未恢復。
此例程可以在原子上下文中執行。
返回
成功時為 0。否則為負錯誤程式碼。
-
void usb_autopm_get_interface_no_resume(struct usb_interface *intf)¶
增加 USB 介面的 PM 使用計數器
引數
struct usb_interface *intf應該增加計數器的 usb_interface
描述
此例程增加 intf 的使用計數器,但不執行自動恢復。
此例程可以在原子上下文中執行。
-
int usb_find_common_endpoints(struct usb_host_interface *alt, struct usb_endpoint_descriptor **bulk_in, struct usb_endpoint_descriptor **bulk_out, struct usb_endpoint_descriptor **int_in, struct usb_endpoint_descriptor **int_out)¶
查詢常見的端點描述符
引數
struct usb_host_interface *alt要搜尋的備用設定
struct usb_endpoint_descriptor **bulk_in指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **bulk_out指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **int_in指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **int_out指向描述符指標的指標,或 NULL
描述
在備用設定的端點描述符中搜索第一個批次輸入、批次輸出、中斷輸入和中斷輸出端點,並在提供的指標中返回它們(除非它們為 NULL)。
如果找不到請求的端點,則會將相應的指標設定為 NULL。
返回
如果找到所有請求的描述符,則為零,否則為 -ENXIO。
-
int usb_find_common_endpoints_reverse(struct usb_host_interface *alt, struct usb_endpoint_descriptor **bulk_in, struct usb_endpoint_descriptor **bulk_out, struct usb_endpoint_descriptor **int_in, struct usb_endpoint_descriptor **int_out)¶
查詢常見的端點描述符
引數
struct usb_host_interface *alt要搜尋的備用設定
struct usb_endpoint_descriptor **bulk_in指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **bulk_out指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **int_in指向描述符指標的指標,或 NULL
struct usb_endpoint_descriptor **int_out指向描述符指標的指標,或 NULL
描述
在備用設定的端點描述符中搜索最後一個批次輸入、批次輸出、中斷輸入和中斷輸出端點,並在提供的指標中返回它們(除非它們為 NULL)。
如果找不到請求的端點,則會將相應的指標設定為 NULL。
返回
如果找到所有請求的描述符,則為零,否則為 -ENXIO。
-
bool usb_check_bulk_endpoints(const struct usb_interface *intf, const u8 *ep_addrs)¶
檢查介面的當前備用設定是否包含一組具有給定地址的批次端點。
引數
const struct usb_interface *intf應該搜尋其當前備用設定的介面
const u8 *ep_addrs要查詢的端點地址(編號和方向)的 0 終止陣列
描述
搜尋具有指定地址的端點並檢查其型別。
返回
如果找到所有端點並且是批次端點,則為 true,否則為 false。
-
bool usb_check_int_endpoints(const struct usb_interface *intf, const u8 *ep_addrs)¶
檢查介面的當前備用設定是否包含一組具有給定地址的中斷端點。
引數
const struct usb_interface *intf應該搜尋其當前備用設定的介面
const u8 *ep_addrs要查詢的端點地址(編號和方向)的 0 終止陣列
描述
搜尋具有指定地址的端點並檢查其型別。
返回
如果找到所有端點並且是中斷端點,則為 true,否則為 false。
-
struct usb_host_interface *usb_find_alt_setting(struct usb_host_config *config, unsigned int iface_num, unsigned int alt_num)¶
給定配置,查詢給定介面的備用設定。
引數
struct usb_host_config *config要搜尋的配置(不一定是當前配置)。
unsigned int iface_num要在其中搜索的介面編號
unsigned int alt_num要搜尋的備用介面設定編號。
描述
在配置的介面快取中搜索給定的備用設定。
返回
備用設定(如果找到)。否則為 NULL。
-
struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum)¶
獲取具有給定介面編號的介面物件
引數
const struct usb_device *dev考慮其當前配置的裝置
unsigned ifnum所需的介面
描述
這將遍歷當前活動配置的裝置描述符,以查詢具有特定介面編號的介面物件。
請注意,配置描述符不需要按順序分配介面編號,因此假設該描述符中的第一個介面對應於介面零是不正確的。此例程可幫助裝置驅動程式避免此類錯誤。但是,您應確保對該介面的任何備用設定都執行正確的操作。
除非您繫結到此裝置上的某個介面或您已鎖定該裝置,否則不要呼叫此函式!
返回
指向具有 ifnum 作為介面編號的介面的指標(如果找到)。否則為 NULL。
-
struct usb_host_interface *usb_altnum_to_altsetting(const struct usb_interface *intf, unsigned int altnum)¶
獲取具有給定備用設定編號的備用設定結構。
引數
const struct usb_interface *intf包含相關備用設定的介面
unsigned int altnum所需的備用設定編號
描述
這會在指定介面的備用設定陣列中搜索具有正確 bAlternateSetting 值的條目。
請注意,備用設定不需要按數字順序儲存,因此假設陣列中的第一個備用設定條目對應於備用設定零是不正確的。此例程可幫助裝置驅動程式避免此類錯誤。
除非您繫結到 intf 介面或您已鎖定該裝置,否則不要呼叫此函式!
返回
指向 intf 的備用設定陣列中具有 altnum 作為備用設定編號的條目的指標。如果未找到,則為 NULL。
-
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)¶
查詢驅動程式和裝置的 usb_interface 指標
引數
struct usb_driver *drv考慮其當前配置的驅動程式
int minor所需裝置的次要編號
描述
這將遍歷匯流排裝置列表,並返回指向具有匹配的次要編號和驅動程式的介面的指標。請注意,這僅適用於共享 USB 主編號的裝置。
返回
指向具有匹配的主編號和 minor 的介面的指標。
-
int usb_for_each_dev(void *data, int (*fn)(struct usb_device*, void*))¶
迭代系統中的所有 USB 裝置
引數
void *data將傳遞給回撥函式的資料指標
int (*fn)(struct usb_device *, void *)要為每個 USB 裝置呼叫的回撥函式
描述
迭代所有 USB 裝置併為每個裝置呼叫 fn,傳遞 data。如果它返回除 0 以外的任何值,我們將提前中斷迭代並返回該值。
-
struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)¶
usb 裝置建構函式(usbcore 內部)
引數
struct usb_device *parent裝置連線到的集線器;如果分配根集線器,則為 null
struct usb_bus *bus用於訪問裝置的匯流排
unsigned port1埠的從一開始的索引;對於根集線器將被忽略
上下文
任務上下文,可能會睡眠。
描述
只有集線器驅動程式(包括主機控制器的虛擬根集線器驅動程式)才應呼叫此函式。
此呼叫可能無法在非睡眠上下文中使用。
返回
成功時,指向分配的 usb 裝置的指標。失敗時為 NULL。
-
struct usb_device *usb_get_dev(struct usb_device *dev)¶
增加 usb 裝置結構的引用計數
引數
struct usb_device *dev正在引用的裝置
描述
對裝置的每個即時引用都應進行引用計數。
USB 介面的驅動程式通常應在其 probe() 方法中記錄此類引用(在它們繫結到介面時),並透過在其 disconnect() 方法中呼叫 usb_put_dev() 來釋放它們。但是,如果驅動程式在其 disconnect() 方法返回後不訪問 usb_device 結構,則不需要引用計數,因為 USB 核心保證在取消繫結其所有介面驅動程式之前,不會取消分配 usb_device。
返回
指向具有遞增的引用計數器的裝置的指標。
-
void usb_put_dev(struct usb_device *dev)¶
釋放 usb 裝置結構的使用
引數
struct usb_device *dev已斷開連線的裝置
描述
必須在裝置的使用者完成使用裝置後呼叫。當裝置的最後一個使用者呼叫此函式時,將釋放裝置的記憶體。
-
struct usb_interface *usb_get_intf(struct usb_interface *intf)¶
增加 usb 介面結構的引用計數
引數
struct usb_interface *intf正在引用的介面
描述
對介面的每個即時引用都必須進行引用計數。
USB 介面的驅動程式通常應在其 probe() 方法中記錄此類引用(在它們繫結到介面時),並透過在其 disconnect() 方法中呼叫 usb_put_intf() 來釋放它們。但是,如果驅動程式在其 disconnect() 方法返回後不訪問 usb_interface 結構,則不需要引用計數,因為 USB 核心保證在其驅動程式已取消繫結之前,不會取消分配 usb_interface。
返回
指向具有遞增的引用計數器的介面的指標。
-
void usb_put_intf(struct usb_interface *intf)¶
釋放 usb 介面結構的使用
引數
struct usb_interface *intf已減少的介面
描述
必須在介面的使用者完成使用介面後呼叫。當介面的最後一個使用者呼叫此函式時,將釋放介面的記憶體。
-
struct device *usb_intf_get_dma_device(struct usb_interface *intf)¶
獲取對 usb 介面的 DMA 端點的引用
引數
struct usb_interface *intfusb 介面
描述
雖然 USB 裝置本身無法執行 DMA 操作,但許多 USB 控制器可以執行 DMA 操作。呼叫 usb_intf_get_dma_device() 返回給定 USB 介面的 DMA 端點(如果有)。返回的裝置結構必須使用 put_device() 釋放。
另請參閱 usb_get_dma_device()。
返回
- 對 usb 介面的 DMA 端點的引用;如果不存在,則為 NULL
。
-
int usb_lock_device_for_reset(struct usb_device *udev, const struct usb_interface *iface)¶
謹慎地獲取 usb 裝置結構的鎖
引數
struct usb_device *udev正在鎖定的裝置
const struct usb_interface *iface繫結到發出請求的驅動程式的介面(可選)
描述
嘗試獲取裝置鎖,但如果裝置為 NOTATTACHED 或 SUSPENDED,或者如果指定了 iface 且介面既不是 BINDING 也不是 BOUND,則會失敗。該例程會重複輪詢,而不是進入睡眠狀態來等待鎖。這是為了防止與斷開連線的死鎖;在某些驅動程式(例如 usb-storage)中,disconnect() 或 suspend() 方法會阻塞以等待裝置重置完成。
返回
失敗時為負錯誤程式碼,否則為 0。
-
int usb_get_current_frame_number(struct usb_device *dev)¶
返回當前匯流排幀編號
引數
struct usb_device *dev正在查詢其匯流排的裝置
返回
與給定 USB 裝置一起使用的 USB 主機控制器的當前幀編號。這可以在計劃等時請求時使用。
Note
不同型別的主機控制器具有不同的“計劃範圍”。雖然一種型別可能僅支援在未來 32 幀內進行計劃,但其他型別可能支援在未來最多 1024 幀內進行計劃。
-
void *usb_alloc_coherent(struct usb_device *dev, size_t size, gfp_t mem_flags, dma_addr_t *dma)¶
為 URB_NO_xxx_DMA_MAP 分配 dma 一致的緩衝區
引數
struct usb_device *dev將使用緩衝區的裝置
size_t size請求的緩衝區大小
gfp_t mem_flags影響分配是否可能阻止
dma_addr_t *dma用於返回緩衝區的 DMA 地址
返回
要麼為 null(指示無法分配緩衝區),要麼為 cpu 空間指標,指向可用於對指定裝置執行 DMA 的緩衝區。此類 cpu 空間緩衝區與 DMA 地址一起返回(透過提供的指標)。
Note
這些緩衝區與 urb->transfer_flags 中設定的 URB_NO_xxx_DMA_MAP 一起使用,以避免諸如使用“DMA 彈跳緩衝區”或在 URB 完成/重新提交期間損壞 IOMMU 硬體等行為。實現方式因平臺而異,具體取決於 DMA 對該裝置的工作方式的詳細資訊。使用這些緩衝區還消除了 CPU 快取未 DMA 一致的體系結構上的快取行共享問題。在沒有匯流排監聽快取的系統上,這些緩衝區是未快取的。
描述
當不再使用該緩衝區時,使用 usb_free_coherent() 釋放它。
-
void usb_free_coherent(struct usb_device *dev, size_t size, void *addr, dma_addr_t dma)¶
釋放使用
usb_alloc_coherent()分配的記憶體
引數
struct usb_device *dev使用緩衝區的裝置
size_t size請求的緩衝區大小
void *addr緩衝區的 CPU 地址
dma_addr_t dma緩衝區的 DMA 地址
描述
這會回收一個 I/O 緩衝區,使其可以重複使用。該記憶體必須已使用 usb_alloc_coherent() 分配,並且引數必須與該分配請求中提供的引數匹配。
引數
struct urb *urb與失敗或未完成的分裂事務關聯的 URB
描述
高速 HCD 使用此方法告知集線器驅動程式,某些分裂控制或批次事務失敗,需要清除事務轉換器的內部狀態。這通常是在中斷上下文中檢測到(並報告)。
在完全清除該狀態之前,該集線器可能無法處理其他完全(或低速)事務。
返回
如果成功,則為 0。否則為負錯誤程式碼。
-
void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state)¶
更改裝置的當前狀態(usbcore,hcds)
引數
struct usb_device *udev指向應更改狀態的裝置的指標
enum usb_device_state new_state要儲存的新狀態值
描述
udev->state 未完全受到裝置鎖的保護。雖然大多數轉換僅在持有鎖時進行,但狀態幾乎可以在任何時間更改為 USB_STATE_NOTATTACHED。這是為了儘快將裝置標記為斷開連線,而無需等待任何訊號量釋放。因此,對任何裝置狀態的所有更改都必須受到 device_state_lock 自旋鎖的保護。
一旦裝置被新增到裝置樹中,對其狀態的所有更改都應使用此例程進行。狀態_不應_直接設定。
如果 udev->state 已經是 USB_STATE_NOTATTACHED,則不會進行任何更改。否則,udev->state 將設定為 new_state,如果 new_state 是 USB_STATE_NOTATTACHED,則 udev 的所有後代的狀態也將設定為 USB_STATE_NOTATTACHED。
-
void usb_root_hub_lost_power(struct usb_device *rhdev)¶
如果根集線器失去 Vbus 電源,則由 HCD 呼叫
引數
struct usb_device *rhdev根集線器的
struct usb_device
描述
當 USB 主機控制器驅動程式恢復其根集線器並且 Vbus 電源已中斷或控制器已重置時,它會呼叫此函式。該例程將 **rhdev** 標記為已斷電。當集線器驅動程式恢復時,它會注意到這一點,併為所有啟用“USB-PERSIST”的子裝置執行電源會話恢復;其他裝置將被斷開連線。
-
int usb_reset_device(struct usb_device *udev)¶
警告介面驅動程式並執行 USB 埠重置
引數
struct usb_device *udev要重置的裝置(不在 NOTATTACHED 狀態)
描述
警告繫結到已註冊介面的所有驅動程式(使用其 pre_reset 方法),執行埠重置,然後讓驅動程式知道重置已完成(使用其 post_reset 方法)。
如果當前正在探測或斷開連線介面,我們假設其驅動程式知道如何處理重置。對於所有其他介面,如果驅動程式沒有 pre_reset 和 post_reset 方法,我們將嘗試取消繫結它並在之後重新繫結。
返回
與 usb_reset_and_verify_device() 相同。但是,如果重置已經在進行中(例如,如果驅動程式沒有 pre_reset() 或 post_reset() 回撥,並且在正在進行的重置期間取消繫結或重新繫結時,其 disconnect() 或 probe() 例程嘗試執行第二次巢狀重置),則該例程返回 -EINPROGRESS。
Note
呼叫者必須擁有裝置鎖。例如,在下載新韌體後,從此驅動程式 probe() 例程中使用它是安全的。對於可能不會在 probe() 期間發生的呼叫,驅動程式應使用 usb_lock_device_for_reset() 鎖定裝置。
-
void usb_queue_reset_device(struct usb_interface *iface)¶
從原子上下文中重置 USB 裝置
引數
struct usb_interface *iface屬於要重置的裝置的 USB 介面
描述
此函式可用於從原子上下文中重置 USB 裝置,其中 usb_reset_device() 將無法工作(因為它會阻塞)。
透過此方法進行重置在功能上等同於呼叫 usb_reset_device(),但不同之處在於它被延遲到工作佇列。這意味著繫結到其他介面的任何驅動程式都可能被取消繫結,以及使用者空間 usbfs 中的使用者。
特殊情況
從連線到同一裝置的不同介面的兩個不同驅動程式同時排程兩次重置是可能的;根據連線到每個介面的驅動程式如何處理 ->pre_reset(),第二次重置可能會發生或不會發生。
如果重置延遲太久以至於介面與其驅動程式解除繫結,則將跳過重置。
可以在 .probe() 期間呼叫此函式。也可以在 .disconnect() 期間呼叫它,但這樣做毫無意義,因為不會發生重置。如果您真的想在 .disconnect() 期間重置裝置,請直接呼叫
usb_reset_device()-- 但請注意巢狀的取消繫結問題!
-
struct usb_device *usb_hub_find_child(struct usb_device *hdev, int port1)¶
獲取連線到由 **port1** 指定的埠的子裝置的指標。
引數
struct usb_device *hdev屬於 USB 集線器的 USB 裝置
int port1埠號,指示子裝置連線到哪個埠。
描述
USB 驅動程式呼叫此函式以獲取集線器的子裝置指標。
返回
如果輸入引數無效,則為 NULL,如果 child 的 usb_device 指標不為 NULL,則為 child 的 usb_device 指標。
主機控制器 API¶
這些 API 僅供主機控制器驅動程式使用,其中大多數實現了標準暫存器介面,例如 XHCI、EHCI、OHCI 或 UHCI。UHCI 是最早的介面之一,由 Intel 設計,VIA 也使用;它在硬體中沒有做太多工作。OHCI 是稍後設計的,目的是讓硬體做更多的工作(更大的傳輸、跟蹤協議狀態等等)。EHCI 是使用 USB 2.0 設計的;它的設計具有類似於 OHCI 的功能(硬體做了更多的工作)以及 UHCI(ISO 支援、TD 列表處理的某些部分)。XHCI 是使用 USB 3.0 設計的。它繼續將對功能的支援轉移到硬體中。
除了“三大”之外,還有其他主機控制器,儘管大多數基於 PCI 的控制器(以及一些非基於 PCI 的控制器)都使用這些介面之一。並非所有主機控制器都使用 DMA;有些使用 PIO,還有一個模擬器和一個虛擬主機控制器透過網路傳輸 USB。
相同的基本 API 可供所有這些控制器的驅動程式使用。由於歷史原因,它們分為兩層:struct usb_bus 是一個相當薄的層,在 2.2 核心中可用,而 struct usb_hcd 是一個功能更強大的層,允許 HCD 共享通用程式碼,以縮小驅動程式大小並顯著減少特定於 hcd 的行為。
-
long usb_calc_bus_time(int speed, int is_input, int isoc, int bytecount)¶
以納秒為單位的近似週期性事務時間
引數
int speed來自 dev->speed; USB_SPEED_{LOW,FULL,HIGH}
int is_input如果事務將資料傳送到主機,則為 true
int isoc對於同步事務為 true,對於中斷事務為 false
int bytecount事務中有多少位元組。
返回
週期性事務的近似匯流排時間(以納秒為單位)。
Note
請參閱 USB 2.0 規範第 5.11.3 節;只有週期性傳輸需要在軟體中排程,此函式僅用於此類排程。
引數
struct usb_hcd *hcdURB 提交到的主機控制器
struct urb *urb正在提交的 URB
描述
主機控制器驅動程式應在其 enqueue() 方法中呼叫此例程。必須持有 HCD 的私有自旋鎖,並且必須停用中斷。此處執行的操作是 URB 提交、端點關閉和 usb_kill_urb 所必需的。
返回
0 表示沒有錯誤,否則為負錯誤程式碼(在這種情況下,enqueue() 方法必須失敗)。如果沒有發生錯誤,但 enqueue() 仍然失敗,則必須在釋放私有自旋鎖並返回之前呼叫 usb_hcd_unlink_urb_from_ep()。
引數
struct usb_hcd *hcdURB 提交到的主機控制器
struct urb *urb正在檢查是否可以取消連結的 URB
int status如果取消連結成功,則儲存在 **urb** 中的錯誤程式碼
描述
主機控制器驅動程式應在其 dequeue() 方法中呼叫此例程。必須持有 HCD 的私有自旋鎖,並且必須停用中斷。此處執行的操作對於確保取消連結有效是必需的。
返回
0 表示沒有錯誤,否則為負錯誤程式碼(在這種情況下,dequeue() 方法必須失敗)。可能的錯誤程式碼為
- -EIDRM:**urb** 未提交或已完成。
完成函式可能尚未被呼叫。
-EBUSY:**urb** 已經被取消連結。
引數
struct usb_hcd *hcdURB 提交到的主機控制器
struct urb *urb正在取消連結的 URB
描述
主機控制器驅動程式應在呼叫 usb_hcd_giveback_urb() 之前呼叫此例程。必須持有 HCD 的私有自旋鎖,並且必須停用中斷。此處執行的操作是 URB 完成所必需的。
引數
struct usb_hcd *hcd正在返回 URB 的主機控制器
struct urb *urb正在返回到 USB 裝置驅動程式的 URB。
int statusURB 的完成狀態程式碼。
上下文
原子的。完成回撥在呼叫者的上下文中呼叫。對於設定了 HCD_BH 標誌的 HCD,完成回撥在 BH 上下文中呼叫(提交到根集線器的 URB 除外,它們始終在呼叫者的上下文中完成)。
描述
這使用 URB 的完成函式將 URB 從 HCD 傳遞到其 USB 裝置驅動程式。HCD 已釋放所有每個 urb 的資源(並且已完成使用 urb->hcpriv)。它還釋放了所有 HCD 鎖;如果裝置驅動程式釋放、修改或重新提交此 URB,則不會導致問題。
如果 **urb** 被取消連結,**status** 的值將被 **urb->unlinked** 覆蓋。如果在 HCD 沒有檢查它們的情況下檢測到錯誤的短傳輸。
-
int usb_alloc_streams(struct usb_interface *interface, struct usb_host_endpoint **eps, unsigned int num_eps, unsigned int num_streams, gfp_t mem_flags)¶
分配批次端點流 ID。
引數
struct usb_interface *interface包含所有端點的備用設定。
struct usb_host_endpoint **eps需要流的端點陣列。
unsigned int num_eps陣列中端點的數量。
unsigned int num_streams要分配的流的數量。
gfp_t mem_flagshcd 應用於分配記憶體的標誌。
描述
設定一組批次端點以具有 **num_streams** 可用的流 ID。驅動程式可以將多個傳輸排隊到不同的流 ID,這些傳輸可能以與排隊順序不同的順序完成。
返回
成功時,為分配的流的數量。失敗時,為負錯誤程式碼。
-
int usb_free_streams(struct usb_interface *interface, struct usb_host_endpoint **eps, unsigned int num_eps, gfp_t mem_flags)¶
釋放批次端點流 ID。
引數
struct usb_interface *interface包含所有端點的備用設定。
struct usb_host_endpoint **eps從中刪除流的端點陣列。
unsigned int num_eps陣列中端點的數量。
gfp_t mem_flagshcd 應用於分配記憶體的標誌。
描述
將一組批次端點恢復為不使用流 ID。如果我們給出了錯誤的引數,或者 HCD 損壞,則可能會失敗。
返回
成功時為 0。失敗時,為負錯誤程式碼。
-
void usb_hcd_resume_root_hub(struct usb_hcd *hcd)¶
由 HCD 呼叫以恢復其根集線器
引數
struct usb_hcd *hcd此根集線器的主機控制器
描述
當 USB 主機控制器掛起其根集線器(啟用了遠端喚醒功能)並且收到遠端喚醒請求時,它會呼叫此函式。該例程提交一個工作佇列請求以恢復根集線器(即,再次管理其下游埠)。
-
int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)¶
開始立即列舉(對於 OTG)
引數
struct usb_bus *bus匯流排(必須使用 hcd 框架)
unsigned port_num埠的基於 1 的編號;通常為 bus->otg_port
上下文
原子的
描述
啟動列舉,立即重置,然後 hub_wq 識別並可能配置裝置。OTG 控制器驅動程式需要這樣做,它可以幫助滿足 HNP 協議對啟動埠重置的時序要求。
返回
如果成功,則為 0。
-
irqreturn_t usb_hcd_irq(int irq, void *__hcd)¶
將 IRQ 掛接到 HCD 框架(匯流排膠水)
引數
int irq正在引發的 IRQ
void *__hcd指向正在發出訊號的 IRQ 的 HCD 的指標
描述
如果控制器未 HALTed,則呼叫驅動程式的 irq 處理程式。檢查控制器現在是否已死。
返回
如果已處理 IRQ,則為 IRQ_HANDLED。否則為 IRQ_NONE。
-
void usb_hc_died(struct usb_hcd *hcd)¶
報告主機控制器的異常關閉(匯流排膠水)
引數
struct usb_hcd *hcd指向表示控制器的 HCD 的指標
描述
匯流排膠水呼叫此函式以報告 USB 主機控制器在操作可能仍在掛起時宕機。PCI 膠水會自動呼叫它,因此只有非 PCI 匯流排的膠水才需要呼叫它。
僅使用主 HCD 呼叫此函式。
建立並初始化 HCD 結構
引數
const struct hc_driver *driver將使用此 hcd 的 HC 驅動程式
struct device *dev此 HC 的裝置,儲存在 hcd->self.controller 中
const char *bus_name要儲存在 hcd->self.bus_name 中的值
struct usb_hcd *primary_hcd指向共享 PCI 裝置的 usb_hcd 結構的指標。僅為主 HCD 分配某些資源
上下文
任務上下文,可能會睡眠。
描述
分配一個 struct usb_hcd,並在末尾留出額外的空間用於 HC 驅動程式的私有資料。初始化 hcd 結構的通用成員。
返回
成功時,指向已建立和初始化的 HCD 結構的指標。失敗時(例如,如果記憶體不可用),NULL。
-
struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, struct device *dev, const char *bus_name)¶
建立並初始化 HCD 結構
引數
const struct hc_driver *driver將使用此 hcd 的 HC 驅動程式
struct device *dev此 HC 的裝置,儲存在 hcd->self.controller 中
const char *bus_name要儲存在 hcd->self.bus_name 中的值
上下文
任務上下文,可能會睡眠。
描述
分配一個 struct usb_hcd,並在末尾留出額外的空間用於 HC 驅動程式的私有資料。初始化 hcd 結構的通用成員。
返回
成功時,指向已建立和初始化的 HCD 結構的指標。失敗時(例如,如果記憶體不可用),NULL。
-
int usb_add_hcd(struct usb_hcd *hcd, unsigned int irqnum, unsigned long irqflags)¶
完成通用 HCD 結構初始化和註冊
引數
struct usb_hcd *hcd要初始化的 usb_hcd 結構
unsigned int irqnum要分配的中斷線
unsigned long irqflags中斷型別標誌
描述
完成通用 HCD 初始化的剩餘部分:分配一致記憶體的緩衝區、註冊匯流排、請求 IRQ 線以及呼叫驅動程式的 reset() 和 start() 例程。
-
void usb_remove_hcd(struct usb_hcd *hcd)¶
通用 HCD 的關閉處理
引數
struct usb_hcd *hcd要刪除的 usb_hcd 結構
上下文
任務上下文,可能會睡眠。
描述
斷開根集線器,然後反轉 usb_add_hcd() 的影響,呼叫 HCD 的 stop() 方法。
-
int usb_hcd_pci_probe(struct pci_dev *dev, const struct hc_driver *driver)¶
初始化基於 PCI 的 HCD
引數
struct pci_dev *dev正在探測的 USB 主機控制器
const struct hc_driver *driverUSB HC 驅動程式控制代碼
上下文
任務上下文,可能會休眠
描述
為此 USB 主機控制器分配基本的 PCI 資源,然後透過熱插拔條目的 driver_data 呼叫與其關聯的 HCD 的 start() 方法。
將此函式儲存在 HCD 的 struct pci_driver 中作為 probe()。
返回
如果成功,則為 0。
-
void usb_hcd_pci_remove(struct pci_dev *dev)¶
基於 PCI 的 HCD 的關閉處理
引數
struct pci_dev *dev正在刪除的 USB 主機控制器
上下文
任務上下文,可能會休眠
描述
反轉 usb_hcd_pci_probe() 的效果,首先呼叫 HCD 的 stop() 方法。它始終從執行緒上下文中呼叫,通常是“rmmod”、“apmd”或類似的東西。
將此函式儲存在 HCD 的 struct pci_driver 中作為 remove()。
-
void usb_hcd_pci_shutdown(struct pci_dev *dev)¶
關閉主機控制器
引數
struct pci_dev *devUSB主機控制器正在關閉
-
int hcd_buffer_create(struct usb_hcd *hcd)¶
初始化緩衝區池
引數
struct usb_hcd *hcd要初始化緩衝區池的匯流排
上下文
任務上下文,可能會休眠
描述
作為初始化使用DMA記憶體分配器的主機控制器的一部分呼叫此函式。它初始化一些DMA一致的記憶體池,這些記憶體池將由使用該控制器的所有驅動程式共享。
呼叫 hcd_buffer_destroy() 以在使用這些池後進行清理。
返回
如果成功,則為0。否則為負的errno值。
-
void hcd_buffer_destroy(struct usb_hcd *hcd)¶
釋放緩衝區池
USB字元裝置節點¶
本章介紹Linux字元裝置節點。您可能更喜歡避免為您的USB驅動程式編寫新的核心程式碼。使用者模式裝置驅動程式通常打包為應用程式或庫,並且可以使用一些封裝它的程式設計庫來使用字元裝置。這樣的庫包括
可以在USB指南的“USB裝置檔案系統”部分中看到一些關於它的舊資訊。USB指南的最新副本可以在 http://www.linux-usb.org/ 找到
Note
它們曾經透過 *usbfs* 實現,但這不是sysfs除錯介面的一部分。
這個特定的文件是不完整的,尤其是在非同步模式方面。截至核心2.5.66,程式碼和這個(新的)文件需要交叉審查。
“devtmpfs”中有哪些檔案?¶
通常掛載在 /dev/bus/usb/, usbfs 的功能包括
/dev/bus/usb/BBB/DDD... 魔術檔案暴露每個裝置的配置描述符,並支援一系列的ioctl來發出裝置請求,包括到裝置的I/O。(純粹是為了程式訪問。)
每個匯流排都給出一個數字 (BBB),基於它被列舉的時間;在每個匯流排中,每個裝置都給出一個類似的數字 (DDD)。這些 BBB/DDD 路徑不是“穩定的”識別符號;即使您始終將裝置插入到同一集線器埠,也期望它們會發生變化。*甚至不要考慮將這些儲存在應用程式配置檔案中。* 穩定的識別符號是可用的,對於想要使用它們的使用者模式應用程式。HID和網路裝置暴露這些穩定的ID,因此例如您可以確定您告訴正確的UPS關閉其第二個伺服器。請注意,它(尚未)暴露這些ID。
/dev/bus/usb/BBB/DDD¶
以以下基本方式之一使用這些檔案
它們可以被讀取, 首先生成裝置描述符(18位元組),然後生成當前配置的描述符。有關這些二進位制資料格式的詳細資訊,請參閱USB 2.0規範。您需要將大多數多位元組值從小端格式轉換為您的本機主機位元組序,儘管裝置描述符中的一些欄位(兩個BCD編碼的欄位,以及供應商和產品ID)將被為您位元組交換。請注意,配置描述符包括介面、備選設定、端點以及可能的其他類描述符的描述符。
執行USB操作 使用 ioctl() 請求來發出端點I/O請求(同步或非同步)或管理裝置。這些請求需要
CAP_SYS_RAWIO功能,以及檔案系統訪問許可權。一次只能對這些裝置檔案之一發出一個ioctl請求。這意味著如果您從一個執行緒同步讀取一個端點,那麼在讀取完成之前,您將無法從另一個執行緒寫入不同的端點。這適用於 *半雙工* 協議,但否則您將使用非同步i/o請求。
每個連線的USB裝置都有一個檔案。BBB 指示匯流排編號。DDD 指示該總線上的裝置地址。這兩個數字都是按順序分配的,並且可以重複使用,因此您不能依靠它們來穩定地訪問裝置。例如,裝置在仍然連線時重新列舉是相對常見的(可能有人晃動了它們的電源,集線器或USB電纜),因此裝置可能在您首次連線時是 002/027,然後在稍後的某個時間是 002/048。
這些檔案可以作為二進位制資料讀取。二進位制資料首先由裝置描述符組成,然後是裝置每個配置的描述符。裝置描述符中的多位元組欄位由核心轉換為主機位元組序。配置描述符是匯流排位元組序格式!配置描述符相隔wTotalLength位元組。如果裝置返回的配置描述符資料少於wTotalLength指示的資料,則檔案中將存在缺失位元組的空洞。此資訊也以文字形式顯示在 /sys/kernel/debug/usb/devices 檔案中,稍後將對此進行描述。
這些檔案也可以用於為USB裝置編寫使用者級驅動程式。您可以開啟 /dev/bus/usb/BBB/DDD 檔案讀/寫,讀取其描述符以確保它是您期望的裝置,然後使用ioctl呼叫繫結到介面(或多個介面)。您可以向裝置發出更多ioctl,以使用控制、批次或其他型別的USB傳輸與裝置通訊。IOCTL列在 <linux/usbdevice_fs.h> 檔案中,並且在撰寫本文時,原始碼(linux/drivers/usb/core/devio.c)是透過這些檔案訪問裝置的主要參考。
請注意,由於預設情況下這些 BBB/DDD 檔案只能由root寫入,因此只有root可以編寫此類使用者模式驅動程式。您可以使用 chmod 選擇性地授予其他使用者讀/寫許可權。此外,usbfs掛載選項(如 devmode=0666)可能很有用。
使用者模式驅動程式的生命週期¶
這樣的驅動程式首先需要找到它可以處理的裝置的裝置檔案。也許是因為 /sbin/hotplug 事件處理代理選擇該驅動程式來處理新裝置。或者,它可能是一個掃描所有 /dev/bus/usb 裝置檔案並忽略大多數裝置的應用程式。無論哪種情況,它都應該從裝置檔案中 read() 所有描述符,並根據它可以處理的內容檢查它們。它可能只是拒絕除了特定供應商和產品ID之外的所有內容,或者需要更復雜的策略。
永遠不要假設一次系統上只有一個這樣的裝置!如果您的程式碼一次無法處理多個裝置,至少要檢測到何時有多個裝置,並讓您的使用者選擇要使用的裝置。
一旦您的使用者模式驅動程式知道要使用哪個裝置,它就會以兩種樣式中的任何一種與它互動。簡單的樣式是隻發出控制請求;一些裝置不需要比這些更復雜的互動。(一個例子可能是使用特定於供應商的控制請求進行一些初始化或配置任務的軟體,其餘部分由核心驅動程式完成。)
更可能的是,您需要更復雜的樣式驅動程式:使用非控制端點,讀取或寫入資料並宣告對介面的獨佔使用。批次 傳輸最容易使用,但只有它們的同級 中斷 傳輸才能與低速裝置一起使用。中斷和 同步 傳輸都提供服務保證,因為它們的頻寬已被保留。除非您使用非同步呼叫,否則透過usbfs使用此類“定期”傳輸會很麻煩。但是,中斷傳輸也可以以同步“一次性”樣式使用。
當裝置斷開連線時,您的使用者模式驅動程式永遠不需要擔心清理請求狀態,儘管它應該在開始看到ENODEV錯誤時立即關閉其開啟的檔案描述符。
ioctl() 請求¶
要使用這些ioctl,您需要在您的使用者空間程式中包含以下標頭
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <asm/byteorder.h>
標準的USB裝置模型請求,來自USB 2.0規範的“第9章”,自動包含在 <linux/usb/ch9.h> 標頭中。
除非另有說明,此處描述的ioctl請求將更新應用usbfs檔案的修改時間(除非它們失敗)。返回零表示成功;否則,返回標準的USB錯誤程式碼(這些程式碼記錄在 USB錯誤程式碼 中)。
這些檔案中的每一個都多路複用對多個I/O流的訪問,每個端點一個。每個裝置都有一個控制端點(端點零),它支援有限的RPC風格RPC訪問。裝置由 hub_wq(在核心中)設定影響功耗和基本功能等裝置的裝置範圍 配置。端點是USB 介面 的一部分,USB 介面 可能具有影響諸如哪些端點可用的 備選設定。許多裝置只有一個配置和一個介面,因此它們的驅動程式將忽略配置和備選設定。
管理/狀態請求¶
許多usbfs請求並沒有直接處理裝置I/O。它們主要與裝置管理和狀態有關。這些都是同步請求。
- USBDEVFS_CLAIMINTERFACE
這用於強制usbfs宣告一個特定的介面,該介面以前未被usbfs或任何其他核心驅動程式宣告。ioctl引數是一個整數,儲存介面的編號(來自描述符的bInterfaceNumber)。
請注意,如果您的驅動程式在嘗試使用其端點之一之前未宣告介面,並且沒有其他驅動程式已繫結到它,則usbfs會自動宣告該介面。
此宣告將由RELEASEINTERFACE ioctl釋放,或者透過關閉檔案描述符來釋放。此請求不會更新檔案修改時間。
- USBDEVFS_CONNECTINFO
說明裝置是否為低速。ioctl引數指向一個類似這樣的結構
struct usbdevfs_connectinfo { unsigned int devnum; unsigned char slow; };此請求不會更新檔案修改時間。
您無法分辨“非慢速”裝置是以高速(480 MBit/秒)連線,還是僅以全速(12 MBit/秒)連線。 您應該已經知道devnum值,它是裝置檔名的DDD值。
- USBDEVFS_GET_SPEED
返回裝置的速度。速度以數值形式返回,與enum usb_device_speed一致
此請求不會更新檔案修改時間。
- USBDEVFS_GETDRIVER
返回繫結到給定介面的核心驅動程式的名稱(字串)。引數是指向此結構的指標,該結構已被修改
struct usbdevfs_getdriver { unsigned int interface; char driver[USBDEVFS_MAXDRIVERNAME + 1]; };此請求不會更新檔案修改時間。
- USBDEVFS_IOCTL
將來自使用者空間的請求傳遞給核心驅動程式,該核心驅動程式在其註冊的
struct usb_driver中具有ioctl條目struct usbdevfs_ioctl { int ifno; int ioctl_code; void *data; }; /* user mode call looks like this. * 'request' becomes the driver->ioctl() 'code' parameter. * the size of 'param' is encoded in 'request', and that data * is copied to or from the driver->ioctl() 'buf' parameter. */ static int usbdev_ioctl (int fd, int ifno, unsigned request, void *param) { struct usbdevfs_ioctl wrapper; wrapper.ifno = ifno; wrapper.ioctl_code = request; wrapper.data = param; return ioctl (fd, USBDEVFS_IOCTL, &wrapper); }此請求不會更新檔案修改時間。
即使核心驅動程式沒有建立字元或塊特殊裝置,此請求也允許核心驅動程式透過檔案系統操作與使用者模式程式碼進行通訊。它也已用於執行諸如詢問裝置應使用哪個裝置特殊檔案之類的操作。兩個預定義的ioctl用於斷開和重新連線核心驅動程式,以便使用者模式程式碼可以完全管理裝置的繫結和配置。
- USBDEVFS_RELEASEINTERFACE
這用於在檔案描述符關閉之前,釋放usbfs對介面進行的宣告,無論是隱式宣告還是由於USBDEVFS_CLAIMINTERFACE呼叫。ioctl引數是一個整數,儲存介面的編號(來自描述符的bInterfaceNumber);此請求不會更新檔案修改時間。
警告
不進行安全檢查以確保發出宣告的任務是釋放宣告的任務。這意味著使用者模式驅動程式可能會干擾其他驅動程式。
- USBDEVFS_RESETEP
將端點(批次或中斷)的資料切換值重置為DATA0。ioctl引數是一個整數端點號(1到15,如端點描述符中所標識的),如果裝置的端點將資料傳送到主機,則新增USB_DIR_IN。
警告
避免使用此請求。應該將其刪除。 使用它通常意味著裝置和驅動程式將失去切換同步。如果您確實失去了同步,則可能需要使用類似CLEAR_HALT或SET_INTERFACE的請求與裝置完全握手。
- USBDEVFS_DROP_PRIVILEGES
這用於放棄執行某些操作的能力,這些操作被認為是在usbfs檔案描述符上特權的。這包括宣告任意介面,重置裝置上當前來自其他使用者的已宣告介面,以及發出USBDEVFS_IOCTL呼叫。ioctl引數是一個32位介面掩碼,使用者允許在此檔案描述符上宣告該掩碼。您可以多次發出此ioctl以縮小所述掩碼。
同步I/O支援¶
同步請求涉及核心阻塞,直到使用者模式請求完成,無論是成功完成還是報告錯誤。在大多數情況下,這是使用usbfs的最簡單方法,儘管如上所述,它確實阻止了一次對多個端點執行I/O。
- USBDEVFS_BULK
向裝置發出批次讀取或寫入請求。ioctl引數是指向此結構的指標
struct usbdevfs_bulktransfer { unsigned int ep; unsigned int len; unsigned int timeout; /* in milliseconds */ void *data; };ep值標識一個批次端點號(1到15,如端點描述符中所標識的),在引用從裝置向主機發送資料的端點時,使用USB_DIR_IN遮蔽。資料緩衝區的長度由len標識;最近的核心支援高達約128 KBytes的請求。FIXME 說明如何返回讀取長度,以及如何處理短讀取。。- USBDEVFS_CLEAR_HALT
清除端點停止(停止)並重置端點切換。這僅對批次或中斷端點有意義。ioctl引數是一個整數端點號(1到15,如端點描述符中所標識的),在引用從裝置向主機發送資料的端點時,使用USB_DIR_IN遮蔽。
在已停止的批次或中斷端點上使用此方法,從而將
-EPIPE狀態返回到資料傳輸請求。不要直接發出控制請求,因為這可能會使主機的資料切換記錄無效。- USBDEVFS_CONTROL
向裝置發出控制請求。ioctl引數指向一個類似這樣的結構
struct usbdevfs_ctrltransfer { __u8 bRequestType; __u8 bRequest; __u16 wValue; __u16 wIndex; __u16 wLength; __u32 timeout; /* in milliseconds */ void *data; };此結構的前八個位元組是要傳送到裝置的SETUP資料包的內容;有關詳細資訊,請參見USB 2.0規範。bRequestType值是透過組合一個
USB_TYPE_*值、一個USB_DIR_*值和一個USB_RECIP_*值(來自linux/usb.h)構成的。如果wLength非零,則描述資料緩衝區的長度,該緩衝區要麼寫入裝置(USB_DIR_OUT),要麼從裝置讀取(USB_DIR_IN)。在撰寫本文時,您無法將超過4 KBytes的資料傳輸到裝置或從裝置傳輸資料;usbfs有一個限制,並且一些主機控制器驅動程式也有一個限制。(這通常不是問題。)此外 無法說明從裝置返回短讀取是可以接受的。
- USBDEVFS_RESET
執行USB級別裝置重置。ioctl引數被忽略。重置後,這將重新繫結所有裝置介面。此請求不會更新檔案修改時間。
警告
在修復一些usbcore錯誤之前,請避免使用此呼叫,因為它不能完全同步裝置,介面和驅動程式(不僅僅是usbfs)狀態。
- USBDEVFS_SETINTERFACE
設定介面的備用設定。ioctl引數是指向一個類似這樣的結構的指標
struct usbdevfs_setinterface { unsigned int interface; unsigned int altsetting; };此請求不會更新檔案修改時間。
這些結構成員來自適用於當前配置的某些介面描述符。介面號是bInterfaceNumber值,備用設定號是bAlternateSetting值。(這將重置介面中的每個端點。)
- USBDEVFS_SETCONFIGURATION
為裝置發出
usb_set_configuration()呼叫。該引數是一個整數,用於儲存配置的編號(來自描述符的bConfigurationValue)。此請求不會更新檔案修改時間。
警告
在修復一些usbcore錯誤之前,請避免使用此呼叫,因為它不能完全同步裝置,介面和驅動程式(不僅僅是usbfs)狀態。
非同步I/O支援¶
如上所述,在某些情況下,從使用者模式程式碼啟動併發操作可能很重要。這對於定期傳輸(中斷和同步)尤其重要,但它也可以用於其他型別的USB請求。在這種情況下,此處描述的非同步請求至關重要。不是提交一個請求並讓核心阻塞直到完成,而是阻塞是分開的。
這些請求被打包成一個類似於核心裝置驅動程式使用的URB的結構。(此處不提供POSIX非同步I/O支援,抱歉。)它標識端點型別(USBDEVFS_URB_TYPE_*),端點(編號,適當地使用USB_DIR_IN遮蔽),緩衝區和長度,以及一個使用者“上下文”值,用於唯一標識每個請求。(它通常是指向每個請求資料的指標。)標誌可以修改請求(不如核心驅動程式支援的請求那麼多)。
每個請求都可以指定一個即時訊號編號(介於SIGRTMIN和SIGRTMAX之間,包括兩者),以請求在請求完成時傳送一個訊號。
當usbfs返回這些urbs時,狀態值會被更新,並且緩衝區可能已被修改。除了同步傳輸之外,actual_length會更新以說明傳輸了多少位元組;如果設定了USBDEVFS_URB_DISABLE_SPD標誌(“不允許短資料包”),如果讀取的位元組少於請求的位元組,那麼您將收到錯誤報告
struct usbdevfs_iso_packet_desc {
unsigned int length;
unsigned int actual_length;
unsigned int status;
};
struct usbdevfs_urb {
unsigned char type;
unsigned char endpoint;
int status;
unsigned int flags;
void *buffer;
int buffer_length;
int actual_length;
int start_frame;
int number_of_packets;
int error_count;
unsigned int signr;
void *usercontext;
struct usbdevfs_iso_packet_desc iso_frame_desc[];
};
對於這些非同步請求,檔案修改時間反映了請求何時啟動。這與其用於同步請求形成對比,在同步請求中,檔案修改時間反映了請求何時完成。
- USBDEVFS_DISCARDURB
TBS 此請求不會更新檔案修改時間。
- USBDEVFS_DISCSIGNAL
TBS 此請求不會更新檔案修改時間。
- USBDEVFS_REAPURB
TBS 此請求不會更新檔案修改時間。
- USBDEVFS_REAPURBNDELAY
TBS 此請求不會更新檔案修改時間。
- USBDEVFS_SUBMITURB
TBS
USB裝置¶
USB裝置現在透過debugfs匯出
/sys/kernel/debug/usb/devices... 一個文字檔案,顯示核心已知的每個USB裝置及其配置描述符。您也可以輪詢()此檔案以瞭解新裝置。
/sys/kernel/debug/usb/devices¶
此檔案對於使用者模式下的狀態檢視工具很方便,使用者模式工具可以掃描文字格式並忽略其中的大部分內容。更詳細的裝置狀態(包括類和供應商狀態)可以從特定於裝置的檔案中獲得。有關此檔案當前格式的資訊,請參見下文。
此檔案與poll()系統呼叫結合使用,還可以用於檢測何時新增或刪除裝置
int fd;
struct pollfd pfd;
fd = open("/sys/kernel/debug/usb/devices", O_RDONLY);
pfd = { fd, POLLIN, 0 };
for (;;) {
/* The first time through, this call will return immediately. */
poll(&pfd, 1, -1);
/* To see what's changed, compare the file's previous and current
contents or scan the filesystem. (Scanning is more precise.) */
}
請注意,此行為旨在用於資訊和除錯目的。更合適的是使用udev或HAL之類的程式來初始化裝置或啟動使用者模式輔助程式,例如。
在此檔案中,每個裝置的輸出都有多行ASCII輸出。
我故意將其設為ASCII而不是二進位制,以便有人可以在不使用輔助程式的情況下從中獲取一些有用的資料。但是,使用輔助程式,每個 T: 行的前4列(拓撲資訊:Lev,Prnt,Port,Cnt)中的數字可用於構建USB拓撲圖。
每行都標有一個字元ID。
T = Topology (etc.)
B = Bandwidth (applies only to USB host controllers, which are
virtualized as root hubs)
D = Device descriptor info.
P = Product ID info. (from Device descriptor, but they won't fit
together on one line)
S = String descriptors.
C = Configuration descriptor info. (* = active configuration)
I = Interface descriptor info.
E = Endpoint descriptor info.
/sys/kernel/debug/usb/devices 輸出格式¶
- 圖例:
d = 十進位制數(可能具有前導空格或0)x = 十六進位制數(可能具有前導空格或0)s = 字串
拓撲資訊¶
T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd
| | | | | | | | |__MaxChildren
| | | | | | | |__Device Speed in Mbps
| | | | | | |__DeviceNumber
| | | | | |__Count of devices at this level
| | | | |__Connector/Port on Parent for this device
| | | |__Parent DeviceNumber
| | |__Level in topology for this bus
| |__Bus number
|__Topology info tag
速度可以是
1.5
Mbit/s表示低速USB
12
Mbit/s表示全速USB
480
Mbit/s表示高速USB(為USB 2.0新增)
5000
Mbit/s表示SuperSpeed USB(為USB 3.0新增)
由於時光流逝的原因,埠號總是低1。例如,插入埠4的裝置將顯示為 Port=03。
頻寬資訊¶
B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd
| | | |__Number of isochronous requests
| | |__Number of interrupt requests
| |__Total Bandwidth allocated to this bus
|__Bandwidth info tag
頻寬分配是正在使用的一個幀(毫秒)的大致量。它僅反映定期傳輸,這是保留頻寬的唯一傳輸。控制和批次傳輸使用所有其他頻寬,包括未用於傳輸的保留頻寬(例如用於短資料包)。
百分比是這些傳輸計劃使用的“保留”頻寬的多少。對於低速或全速匯流排(鬆散地說是“USB 1.1”),保留了90%的匯流排頻寬。對於高速匯流排(鬆散地說是“USB 2.0”),保留了80%的頻寬。
裝置描述符資訊&產品ID資訊¶
D: Ver=x.xx Cls=xx(s) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
P: Vendor=xxxx ProdID=xxxx Rev=xx.xx
其中
D: Ver=x.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd
| | | | | | |__NumberConfigurations
| | | | | |__MaxPacketSize of Default Endpoint
| | | | |__DeviceProtocol
| | | |__DeviceSubClass
| | |__DeviceClass
| |__Device USB version
|__Device info tag #1
其中
P: Vendor=xxxx ProdID=xxxx Rev=xx.xx
| | | |__Product revision number
| | |__Product ID code
| |__Vendor ID code
|__Device info tag #2
字串描述符資訊¶
S: Manufacturer=ssss
| |__Manufacturer of this device as read from the device.
| For USB host controller drivers (virtual root hubs) this may
| be omitted, or (for newer drivers) will identify the kernel
| version and the driver which provides this hub emulation.
|__String info tag
S: Product=ssss
| |__Product description of this device as read from the device.
| For older USB host controller drivers (virtual root hubs) this
| indicates the driver; for newer ones, it's a product (and vendor)
| description that often comes from the kernel's PCI ID database.
|__String info tag
S: SerialNumber=ssss
| |__Serial Number of this device as read from the device.
| For USB host controller drivers (virtual root hubs) this is
| some unique ID, normally a bus ID (address or slot name) that
| can't be shared with any other device.
|__String info tag
配置描述符資訊¶
C:* #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA
| | | | | |__MaxPower in mA
| | | | |__Attributes
| | | |__ConfiguratioNumber
| | |__NumberOfInterfaces
| |__ "*" indicates the active configuration (others are " ")
|__Config info tag
USB裝置可能具有多個配置,每個配置的行為都截然不同。例如,匯流排供電的配置可能比自供電的配置能力弱得多。一次只能啟用一個裝置配置;大多數裝置只有一個配置。
每個配置由一個或多個介面組成。每個介面都提供一個獨特的“功能”,通常繫結到不同的USB裝置驅動程式。一個常見的例子是帶有用於播放的音訊介面和用於軟體音量控制的HID介面的USB揚聲器。
介面描述符資訊(每個Config可以有多個)¶
I:* If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=ssss
| | | | | | | | |__Driver name
| | | | | | | | or "(none)"
| | | | | | | |__InterfaceProtocol
| | | | | | |__InterfaceSubClass
| | | | | |__InterfaceClass
| | | | |__NumberOfEndpoints
| | | |__AlternateSettingNumber
| | |__InterfaceNumber
| |__ "*" indicates the active altsetting (others are " ")
|__Interface info tag
給定的介面可能具有一個或多個“備用”設定。例如,預設設定可能不會使用超過少量定期頻寬。要使用匯流排頻寬的很大一部分,驅動程式必須選擇非預設的備用設定。
一個介面一次只能啟用一個設定,並且一次只能有一個驅動程式繫結到一個介面。大多數裝置每個介面只有一個備用設定。
端點描述符資訊(每個介面可以有多個)¶
E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddss
| | | | |__Interval (max) between transfers
| | | |__EndpointMaxPacketSize
| | |__Attributes(EndpointType)
| |__EndpointAddress(I=In,O=Out)
|__Endpoint info tag
對於所有定期(中斷或同步)端點,間隔都為非零。對於高速端點,傳輸間隔可以以微秒而不是毫秒為單位進行測量。
對於高速定期端點,EndpointMaxPacketSize 反映了每個微幀的資料傳輸大小。對於“高頻寬”端點,這可以反映每個端點最多三個資料包(對於每125微秒最多3 KBytes)。
使用Linux-USB堆疊,定期頻寬預留使用URB提供的傳輸間隔和大小,這些間隔和大小可能小於端點描述符中的間隔和大小。
用法示例¶
如果使用者或指令碼僅對拓撲資訊感興趣,例如,使用類似 grep ^T: /sys/kernel/debug/usb/devices 僅獲取拓撲行。諸如 grep -i ^[tdp]: /sys/kernel/debug/usb/devices 之類的命令可用於僅列出以方括號中的字元開頭的行,其中有效字元為 TDPCIE。透過稍有能力的指令碼,它可以顯示任何選定的行(例如,僅T,D和P行)並更改其輸出格式。(procusb Perl指令碼是這個想法的開始。它將僅列出來自 /sys/kernel/debug/usb/devices 的選定行[從TBDPSCIE中選擇]或“全部”行。)
拓撲行可用於生成系統根集線器上的USB裝置的圖形/圖片。(有關如何執行此操作的更多資訊,請參見下文。)
介面行可用於確定每個裝置正在使用的驅動程式以及它激活了哪個備用設定。
配置行可用於列出系統USB裝置正在使用的最大功率(以毫安為單位)。例如,grep ^C: /sys/kernel/debug/usb/devices。
這是一個示例,來自具有UHCI根集線器,連線到根集線器的外部集線器以及連線到外部集線器的滑鼠和序列轉換器的系統。
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
B: Alloc= 28/900 us ( 3%), #Int= 2, #Iso= 0
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0000 ProdID=0000 Rev= 0.00
S: Product=USB UHCI Root Hub
S: SerialNumber=dce0
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr= 0mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 8 Ivl=255ms
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
D: Ver= 1.00 Cls=09(hub ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0451 ProdID=1446 Rev= 1.00
C:* #Ifs= 1 Cfg#= 1 Atr=e0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
E: Ad=81(I) Atr=03(Int.) MxPS= 1 Ivl=255ms
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=04b4 ProdID=0001 Rev= 0.00
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
E: Ad=81(I) Atr=03(Int.) MxPS= 3 Ivl= 10ms
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=0565 ProdID=0001 Rev= 1.08
S: Manufacturer=Peracom Networks, Inc.
S: Product=Peracom USB to Serial Converter
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
E: Ad=81(I) Atr=02(Bulk) MxPS= 64 Ivl= 16ms
E: Ad=01(O) Atr=02(Bulk) MxPS= 16 Ivl= 16ms
E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl= 8ms
僅從此選擇 T: 和 I: 行(例如,透過使用 procusb ti),我們有
T: Bus=00 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#= 1 Spd=12 MxCh= 2
T: Bus=00 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 4
I: If#= 0 Alt= 0 #EPs= 1 Cls=09(hub ) Sub=00 Prot=00 Driver=hub
T: Bus=00 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=1.5 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=mouse
T: Bus=00 Lev=02 Prnt=02 Port=02 Cnt=02 Dev#= 4 Spd=12 MxCh= 0
I: If#= 0 Alt= 0 #EPs= 3 Cls=00(>ifc ) Sub=00 Prot=00 Driver=serial
從物理上講,它看起來像這樣(或者可以轉換為)
+------------------+
| PC/root_hub (12)| Dev# = 1
+------------------+ (nn) is Mbps.
Level 0 | CN.0 | CN.1 | [CN = connector/port #]
+------------------+
/
/
+-----------------------+
Level 1 | Dev#2: 4-port hub (12)|
+-----------------------+
|CN.0 |CN.1 |CN.2 |CN.3 |
+-----------------------+
\ \____________________
\_____ \
\ \
+--------------------+ +--------------------+
Level 2 | Dev# 3: mouse (1.5)| | Dev# 4: serial (12)|
+--------------------+ +--------------------+
或者,在更像樹狀的結構中(可以省略沒有連線的埠[聯結器])
PC: Dev# 1, root hub, 2 ports, 12 Mbps
|_ CN.0: Dev# 2, hub, 4 ports, 12 Mbps
|_ CN.0: Dev #3, mouse, 1.5 Mbps
|_ CN.1:
|_ CN.2: Dev #4, serial, 12 Mbps
|_ CN.3:
|_ CN.1: