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.mzph.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;如导航栏、业…