usbredir學習

文章目錄

    • 背景
    • 典型場景
    • 編譯
    • usbredirparser
      • usbredirfilter
      • usbredirparser/usbredirproto
    • usbredirhost
    • usbredirect/usbredirtestclient
    • 參考

背景

usbredir 是一種用于通過網絡轉發 USB 設備流量的網絡協議。它也是一個軟件包的名稱,該軟件包提供了一個解析庫、一個 usbredirhost 庫以及多個實現此協議的工具。
協議的具體內容可以參考usb-redirection-protocol,該文檔還解釋了 usbhost 和 usbguest 的含義。

usbredir 最初是為與 Spice 配合使用而創建的,但該協議和 usbredirhost 完全獨立于 Spice,它們也可以用于創建 VNC 擴展,以便通過 VNC 連接將 USB 設備重定向到 QEMU 虛擬機。

usb guest 端目前僅在 QEMU 中實現,并作為 QEMU 的一部分發布(在 QEMU 中啟用此功能需要在構建 QEMU 時提供 libusbredirparser 庫)。

usbredir 支持通過過濾字符串配置 USB 設備過濾功能。

usbredir項目包含下面幾個庫/工具:

  1. usbredirparser
    一個包含 usbredir 協議解析器的庫。

  2. usbredirhost
    一個實現 usbredir 連接中 usb-host端的庫,這是實際usb設備所連接的一端。
    希望實現 usb-host 的應用程序需要實現:

  • 為設備提供一個 libusb 設備句柄
  • 為 usbredir 數據的實際傳輸提供寫和讀的回調函數
  • 監聽 usbredir 和 libusb 的讀/寫事件,并調用其處理程序
  1. usbredirect
    usbredirect 二進制文件是一個 usbredir 客戶端,用于將 USB 設備導出,以便通過 usbredir 協議從另一臺(虛擬)機器使用。

  2. usbredirtestclient
    一個用于通過 TCP 使用 usbredir 協議 的小型測試客戶端, 其使用usbredirparser庫。

典型場景

一個典型場景:
在這里插入圖片描述

  • usb device:usb設備。
  • client pc:usb設備直接連接的pc,一般是用戶終端(pc或者VDI盒子)。
  • guest vm:連接到usb設備并使用它的桌面(一般是VM),就像直接連接到它一樣。
  • usb host:使usb device可供usb guest使用的程序。

編譯

  1. 下載源碼
$ git clone https://gitlab.freedesktop.org/spice/usbredir.git
  1. 安裝依賴
    參考.gitlab-ci.yml文件里的依賴
# debian環境
sudo apt install gcc clang meson ninja-build valgrind git bzip2 libglib2.0-dev libusb-1.0-0-dev
  1. 編譯
$ meson . _build -Dfuzzing=disabled -Dtools=enabled
$ cd _build
$ meson compile

編譯后,生成產物:
在這里插入圖片描述

usbredirparser

usbredirparser/
├── meson.build
├── strtok_r.c
├── strtok_r.h
├── usbredirfilter.c
├── usbredirfilter.h
├── usbredirparser.c
├── usbredirparser.h
├── usbredirparser.map
├── usbredirproto-compat.h
└── usbredirproto.h	# redirection protocol的相關定義

其中:usbredirfilter.husbredirparser.husbredirproto.h 是提供的對外接口頭文件。

usbredirfilter

首先定義了usbredir的規則:

struct usbredirfilter_rule {int device_class;       /* 0-255, -1 to match any class */int vendor_id;          /* 0-65535, -1 to match any id */int product_id;         /* 0-65535, -1 to match any id */int device_version_bcd; /* 0-65535, -1 to match any version */int allow;              /* 0: deny redir for this device, non 0: allow */
};

通過該規則可以過濾哪些usb設備可以重定向哪些不可以。
隨后定義了規則的轉換函數:

int usbredirfilter_string_to_rules(const char *filter_str, const char *token_sep, const char *rule_sep,struct usbredirfilter_rule **rules_ret, int *rules_count_ret);
char *usbredirfilter_rules_to_string(const struct usbredirfilter_rule *rules,int rules_count, const char *token_sep, const char *rule_sep);

通過這兩個函數可以在字符串和規則之間轉換。
下面是檢查函數,用戶檢查一個設備是否允許重定向:

int usbredirfilter_check(const struct usbredirfilter_rule *rules, int rules_count,uint8_t device_class, uint8_t device_subclass, uint8_t device_protocol,uint8_t *interface_class, uint8_t *interface_subclass,uint8_t *interface_protocol, int interface_count,uint16_t vendor_id, uint16_t product_id, uint16_t device_version_bcd,int flags);

對傳入的規則進行完整性檢查:

int usbredirfilter_verify(const struct usbredirfilter_rule *rules, int rules_count);

將規則打印到文件中:

void usbredirfilter_print(const struct usbredirfilter_rule *rules, int rules_count, FILE *out);

最后,釋放庫所分配的內存:

void usbredirfilter_free(void *ptr);

usbredirparser/usbredirproto

一個usbredir protocol的解析器,用于協議解析,和usbredirproto.h一起。
關于協議這塊,可以參考官方文檔:usb-redirection-protocol或者其他人的總結:USB重定向協議。

usbredirhost

usbredirhost/
├── meson.build
├── usbredirhost.c
├── usbredirhost.h
└── usbredirhost.map

其中usbredirhost.h是提供的對外接口頭文件。
usbredir的打開與關閉:

struct usbredirhost *usbredirhost_open(libusb_context *usb_ctx,libusb_device_handle *usb_dev_handle,usbredirparser_log log_func,usbredirparser_read  read_guest_data_func,usbredirparser_write write_guest_data_func,void *func_priv, const char *version, int verbose, int flags);/* See docs/multi-thread.md */
struct usbredirhost *usbredirhost_open_full(libusb_context *usb_ctx,libusb_device_handle *usb_dev_handle,usbredirparser_log log_func,usbredirparser_read  read_guest_data_func,usbredirparser_write write_guest_data_func,usbredirhost_flush_writes flush_writes_func,usbredirparser_alloc_lock alloc_lock_func,usbredirparser_lock lock_func,usbredirparser_unlock unlock_func,usbredirparser_free_lock free_lock_func,void *func_priv, const char *version, int verbose, int flags);
void usbredirhost_close(struct usbredirhost *host);

usbredirhost 獲取設備/釋放設備

int usbredirhost_set_device(struct usbredirhost *host,libusb_device_handle *usb_dev_handle);

設置usbredirhost的回調,在usbredirhost_fl_write_cb_owns_buffer標志位有效時,該回調負責返回應用程序的待寫入緩沖區大小(以字節為單位)。

void usbredirhost_set_buffered_output_size_cb(struct usbredirhost *host,usbredirhost_buffered_output_size buffered_output_size_func);

數據處理相關:

int usbredirhost_read_guest_data(struct usbredirhost *host);
int usbredirhost_has_data_to_write(struct usbredirhost *host);
int usbredirhost_write_guest_data(struct usbredirhost *host);
void usbredirhost_free_write_buffer(struct usbredirhost *host, uint8_t *data);

獲取usbredirfilter規則

void usbredirhost_get_guest_filter(struct usbredirhost *host,const struct usbredirfilter_rule **rules_ret, int *rules_count_ret);

檢查usb設備是否允許重定向

int usbredirhost_check_device_filter(const struct usbredirfilter_rule *rules,int rules_count, libusb_device *dev, int flags);

usbredirect/usbredirtestclient

tools
├── meson.build
├── usbredirect.1
└── usbredirect.cusbredirtestclient/
├── meson.build
└── usbredirtestclient.c

運行參數:

$ ./usbredirect
./usbredirect need to act either as client (-to) or as server (-as)
Usage:usbredirect [OPTION?]Help Options:-h, --help          Show help optionsApplication Options:--device            Local USB device to be redirected identified as either VENDOR:PRODUCT "0123:4567" or BUS-DEVICE "5-2"--to                Client URI to connect to--as                Server URI to be run-k, --keepalive     If we should set SO_KEEPALIVE flag on underlying socket-v, --verbose       Set log level between 1-5 where 5 being the most verbose$ ./usbredirtestclient
Missing server argument
Usage: ./usbredirtestclient [-p|--port <port>] [-v|--verbose <0-3>] <server>

測試:

  1. usbredirect 作為server端將usb設備導出
$ sudo ./tools/usbredirect --as 0.0.0.0:5909 --device 058f:6387 --verbose 5

注意看此時系統日志:

[  601.361432] usb-storage 1-12.1:1.0: USB Mass Storage device detected
[  601.361930] scsi host6: usb-storage 1-12.1:1.0
[  601.617526] usb 1-12.1: reset high-speed USB device number 8 using xhci_hcd

被導出的設備被reset掉了,本地lsusb是看不到這個設備了,設備從本地導出了。

  1. usbredirtestclient 連接到server端
    連接到server端:
$ ./usbredirtestclient/usbredirtestclient -p 5909 192.168.0.26
usbredirparser: Peer version: usbredir 0.14.0, using 64-bits ids
interface 0 class  8 subclass  6 protocol 80
endpoint: 00, type: 0, interval: 0, interface: 0 max-packetsize: 0
endpoint: 01, type: 2, interval: 0, interface: 0 max-packetsize: 512
endpoint: 80, type: 0, interval: 0, interface: 0 max-packetsize: 0
endpoint: 82, type: 2, interval: 0, interface: 0 max-packetsize: 512
device info: speed: highclass  0 subclass  0 protocol  0vendor 0x058f product 6387
Get config: 1, status: 0
Set config: 1, status: 0
Get alt: 0, interface: 0, status: 0
interface 0 class  8 subclass  6 protocol 80
endpoint: 00, type: 0, interval: 0, interface: 0 max-packetsize: 0
endpoint: 01, type: 2, interval: 0, interface: 0 max-packetsize: 512
endpoint: 80, type: 0, interval: 0, interface: 0 max-packetsize: 0
endpoint: 82, type: 2, interval: 0, interface: 0 max-packetsize: 512
Set alt: 0, interface: 0, status: 0
> help
Available commands:
ctrl <endpoint> <request> <request_type> <value> <index> <length> [data]
quit
help
> quit

在客戶端退出后,看下server端的系統日志:

[  733.420713] usb 1-12.1: reset high-speed USB device number 8 using xhci_hcd
[  733.628274] usb-storage 1-12.1:1.0: USB Mass Storage device detected
[  733.628954] scsi host6: usb-storage 1-12.1:1.0
[  734.654030] scsi 6:0:0:0: Direct-Access     Generic  Flash Disk       8.07 PQ: 0 ANSI: 4
[  734.654755] sd 6:0:0:0: Attached scsi generic sg5 type 0
[  734.657656] sd 6:0:0:0: [sdf] 15728640 512-byte logical blocks: (8.05 GB/7.50 GiB)
[  734.658392] sd 6:0:0:0: [sdf] Write Protect is off
[  734.658399] sd 6:0:0:0: [sdf] Mode Sense: 23 00 00 00
[  734.659086] sd 6:0:0:0: [sdf] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[  734.725772]  sdf: sdf1
[  734.726165] sd 6:0:0:0: [sdf] Attached SCSI removable disk

可以發現,原來導出的設備重新被attach進去了,此時lsusb又可以看到該設備了,設備又回到本地了。

著兩個工具對應的代碼都很短,可以進去看看他們是怎么工作的,核心就是使用usbredirhost和usbredirparser這兩個庫。

參考

usbredir
usbredir
usbredir-0.7內容詳解(一)
spice
USB重定向協議
USB虛擬化和虛擬桌面USB重定向
Spice Usbredirect 性能改進

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/65957.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/65957.shtml
英文地址,請注明出處:http://en.pswp.cn/web/65957.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ESXI 安裝教程(3) ---?vCenter Server 安裝

不涉及復雜的操作此項可不安裝 1.鏡像加載到虛擬光盤 對應的網盤文件 2.打開文件路徑 雙擊運行文件installer.exe 3.調整安裝語言 4.點擊安裝 5. 6. 證書,有效問題導致此提示,非專業網絡管理人員,不知道如何處理,此處點是即可 證書有效開始時間是安裝時間8小時 證書有效結束…

【初識掃盲】逆概率加權

我們正在處理一個存在缺失數據的回歸模型&#xff0c;并且希望采用一種非參數的逆概率加權方法來調整估計&#xff0c;以應對這種缺失數據的情況。 首先&#xff0c;我們需要明確問題的背景。我們有樣本 { ( Y i , X i , r i ) : i 1 , … , n } \left\{\left(Y_i, \boldsym…

極客說|Azure AI Agent Service 結合 AutoGen/Semantic Kernel 構建多智能體解決?案

作者&#xff1a;盧建暉 - 微軟高級云技術布道師 「極客說」 是一檔專注 AI 時代開發者分享的專欄&#xff0c;我們邀請來自微軟以及技術社區專家&#xff0c;帶來最前沿的技術干貨與實踐經驗。在這里&#xff0c;您將看到深度教程、最佳實踐和創新解決方案。關注「極客說」&am…

【集成學習】Boosting算法詳解

文章目錄 1. 集成學習概述2. Boosting算法詳解3. Gradient Boosting算法詳解3.1 基本思想3.2 公式推導 4. Python實現 1. 集成學習概述 集成學習&#xff08;Ensemble Learning&#xff09;是一種通過結合多個模型的預測結果來提高整體預測性能的技術。相比于單個模型&#xf…

小米vela系統(基于開源nuttx內核)——如何使用信號量進行PV操作

如何使用信號量進行PV操作 前言信號量1. 信號量簡介2. NuttX中信號量的創建與使用2.1 Nuttx信號量的初始化和銷毀2.2 信號量的等待和發布 3. 信號量的實際應用&#xff1a;下載任務示例3.1 實際代碼3.2 代碼說明3.3 執行說明 4. 信號量的優勢與應用場景5. 常見應用場景&#xf…

CMake學習筆記(2)

1. 嵌套的CMake 如果項目很大&#xff0c;或者項目中有很多的源碼目錄&#xff0c;在通過CMake管理項目的時候如果只使用一個CMakeLists.txt&#xff0c;那么這個文件相對會比較復雜&#xff0c;有一種化繁為簡的方式就是給每個源碼目錄都添加一個CMakeLists.txt文件&#xff…

旅游網站設計與實現

文末附有完整項目代碼 在當今數字化時代&#xff0c;旅游網站成為人們獲取旅游信息的重要途徑。本文將詳細介紹旅游網站的設計與實現&#xff0c;讓你輕松了解其中的技術奧秘&#xff01; 一、項目背景 隨著社會經濟的發展&#xff0c;人們對精神消費愈發重視&#xff0c;旅游…

【C++】size_t究竟是什么?全面解析與深入拓展

博客主頁&#xff1a; [小????????] 本文專欄: C 文章目錄 &#x1f4af;前言&#x1f4af;一、什么是size_t&#xff1f;為什么需要size_t&#xff1f; &#x1f4af;二、size_t的特性與用途1. size_t是無符號類型示例&#xff1a; 2. size_t的跨平臺適應性示例對…

【物流管理系統 - IDEAJavaSwingMySQL】基于Java實現的物流管理系統導入IDEA教程

有問題請留言或私信 步驟 下載項目源碼&#xff1a;項目源碼 解壓項目源碼到本地 打開IDEA 左上角&#xff1a;文件 → 新建 → 來自現有源代碼的項目 找到解壓在本地的項目源代碼文件&#xff0c;點擊確定&#xff0c;根據圖示步驟繼續導入項目 查看項目目錄&#xff…

ssh2-sftp-client和ssh2配合使用js腳本快速部署項目到服務器

有時候因為服務器不能實現github或者gitlab的自動部署服務&#xff0c;所以就需要使用腳本來實現自動部署&#xff0c;可以省時省力&#xff0c;一勞永逸。這里就使用ssh2-sftp-client和ssh2來實現&#xff0c;即便是需要sudo權限&#xff0c;也是可以的。 1.先將本地打包后的…

深度解析Linux中的調試器gdb/cgdb的使用

Linux下我們編譯好的代碼&#xff0c;無法直接調試 gcc/g默認的工作模式是realse模式 程序要調試的話&#xff0c;必須是debug模式&#xff0c;也就是說編譯的時候要加-g選項 gdb攜帶調試信息的exe 我們現在在文件夾里面創建一個文件lesson11 里面創建一個累加的代碼&…

【Maui】動態菜單實現(綁定數據視圖)

前言 .NET 多平臺應用 UI (.NET MAUI) 是一個跨平臺框架&#xff0c;用于使用 C# 和 XAML 創建本機移動和桌面應用。 使用 .NET MAUI&#xff0c;可從單個共享代碼庫開發可在 Android、iOS、macOS 和 Windows 上運行的應用。 .NET MAUI 是一款開放源代碼應用&#xff0c;是 X…

Bash語言的語法糖

Bash語言的語法糖 引言 在現代編程語言中&#xff0c;“語法糖”是一個非常常見的術語&#xff0c;它指的是那些使代碼更加易讀、易寫的語法特性。盡管這些特性并不改變語言的功能&#xff0c;但它們能顯著提升開發者的編程體驗。在眾多編程語言中&#xff0c;Bash&#xff0…

linux---Nginx詳細教程(包含安裝,網站部署)

Nginx是一個高性能的HTTP和反向代理服務器&#xff0c;也可以用作郵件代理服務器&#xff0c;其以占有內存少、并發能力強、穩定性高、豐富的功能集、低系統資源消耗而聞名。以下是對Nginx的詳細教程&#xff1a; 一、Nginx簡介 Nginx由俄羅斯人開發&#xff0c;第一個公開版…

RNN之:LSTM 長短期記憶模型-結構-理論詳解-及實戰(Matlab向)

0.前言 遞歸&#xff01;循環神經網絡Recurrent Neural Network 循環神經網絡&#xff08;又稱遞歸神經網絡&#xff0c;Recurrent Neural Network&#xff0c;RNN&#xff09;。是一種用于處理序列數據的神經網絡結構&#xff0c;具有記憶功能&#xff0c;能夠捕捉序列中的時…

泛目錄和泛站有什么差別

啥是 SEO 泛目錄&#xff1f; 咱先來說說 SEO 泛目錄是啥。想象一下&#xff0c;你有一個巨大的圖書館&#xff0c;里面的書架上擺滿了各種各樣的書&#xff0c;每一本書都代表著一個網頁。而 SEO 泛目錄呢&#xff0c;就像是一個超級圖書管理員&#xff0c;它的任務就是把這些…

初識@ffmpeg/ffmpeg庫

前言 FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,并且能夠利用它們來創建一個新的流媒體格式的自由軟件項目,它被廣泛應用在視頻處理、音頻處理以及直播領域。其中,@ffmpeg/ffmpeg 是一個將 FFmpeg 編譯為 WebAssembly(WASM)的庫,可支持幾乎所有的音視頻格式。 安裝…

【圖像去噪】論文復現:反向擴散中加入MAP將擴散模型從高斯去噪推廣到真實去噪!DiffusionVI的Pytorch源碼復現,跑通源碼,梳理理論,單卡可執行!

請先看【專欄介紹文章】:【圖像去噪(Image Denoising)】關于【圖像去噪】專欄的相關說明,包含適配人群、專欄簡介、專欄亮點、閱讀方法、定價理由、品質承諾、關于更新、去噪概述、文章目錄、資料匯總、問題匯總(更新中) 完整代碼和訓練好的模型權重文件下載鏈接見本文底…

Windows 藍牙驅動開發-簡介

藍牙(英語&#xff1a;Bluetooth)是一種無線通信技術標準&#xff0c;用來讓固定與移動設備&#xff0c;在短距離間交換資料&#xff0c;以形成個人局域網(PAN)。其使用短波特高頻(UHF)無線電波&#xff0c;經由2.4至2.485 GHz的ISM頻段來進行通信。1994年由電信商愛立信(Erics…

【Vue】全局/局部組件使用流程(Vue2為例)

全局組件和局部組件區別 如何使用 全局組件&#xff1a;全局注冊后&#xff0c;可以在任意頁面中直接使用。局部組件&#xff1a;在頁面中需要先導入子組件路徑&#xff0c;注冊組件才能使用。 適用場景 全局組件&#xff1a;適用于高頻使用的組件&#xff0c;如導航欄、業…