tuna-f1sh/cyme
GitHub: tuna-f1sh/cyme
cyme 是一个跨平台 USB 设备列表工具,旨在提供比 lsusb 更丰富的功能和更好的用户体验。
Stars: 1127 | Forks: 28
```
o
o /---o
/---/---o
o---/
\---\---o
o \---o
o
```
# Cyme
[](https://crates.io/crates/cyme)
[](https://docs.rs/cyme/latest/cyme/)
列出系统 USB 总线和设备。这是一个现代化的跨平台 `lsusb` 替代工具,力求保持兼容性的同时增加新功能。它对系统 USB 总线及其上的设备进行剖析,包括完整的设备描述符。
作为一名嵌入式设备开发者,我经常使用 USB 列表工具,开发此工具是为了弥补我认为 `lsusb` 的不足之处:详细转储通常_过于_冗长,树状视图整体上缺乏有用数据,在非 Linux 平台上几乎无法工作,并且现代终端支持一些功能,使得浏览数据变得更加轻松。
该项目最初是为了快速替换那个几乎无法工作的 [lsusb 脚本](https://github.com/jlhonora/lsusb),同时也是为了让我保持 Rust 项目的熟悉度!就像大多数有趣的项目一样,在我将其开发成跨平台的 `lsusb` 替代品时,它很快就经历了功能蔓延。它最初是一个 macOS `system_profiler` 解析器,后来演变为包含基于 `libusb` 的剖析器以读取完整的设备描述符,现在默认使用纯 Rust 的剖析器 [nusb](https://github.com/kevinmehall/nusb)。
它并不完美,因为最初只是作为 Rust 的复习项目,但我在开发过程中获得了很多乐趣,并希望其他人能觉得它有用并做出贡献。阅读 [lsusb 源代码](https://github.com/gregkh/usbutils/blob/master/lsusb.c)、USB-IF 规范和通用 USB 信息也是一次很好的知识积累。
名字来源于苹果树上的一种花序类型的技术术语:[cyme](https://en.wikipedia.org/wiki/Inflorescence#Determinate_or_cymose) —— 它与苹果相关,并且看起来像一棵 USB 设备树 😃🌸。

# 功能
* 使用 `--lsusb` 参数时与 `lsusb` 兼容。支持所有参数,包括 `--verbose` 输出 —— 完全解析的设备描述符!无参数列表(list)、树状视图(tree)(在非 Linux 上不包括驱动信息)的输出与 `lsusb` 相同,详细输出(verbose)也应匹配(可能存在格式差异)。
* 默认构建是使用 [nusb](https://docs.rs/nusb/latest/nusb) 的原生 Rust 剖析器。
* 类似 `lsusb` 的过滤器,但在打印 `--tree` 时也有效。增加了 `--filter-name`、`--filter-serial`、`--filter-class` 以及隐藏空 `--hide-buses`/`--hide-hubs` 的选项。也可使用 `--filter-exclude` 进行反向过滤。
* 改进的 `--tree` 模式;根据 `--verbose` 的级别,以树状形式显示设备、配置、接口和端点。
* 可控的显示 `--blocks`,包括设备 `--bus-blocks`、配置 `--config-blocks`、接口 `--interface-blocks` 和端点 `--endpoint-blocks`。使用 `--more` 可默认查看更多内容。
* 现代终端功能,支持彩色输出、utf-8 字符以及基于设备数据的图标查找。可关闭或自定义。参见 `--encoding`(字形[默认]、utf8 和 ascii,可确保图标/树状结构在特定编码范围内)、`--color`(auto [默认]、always 和 never)和 `--icon`(auto [默认]、always 和 never)。自动 `--icon` 仅在所有要显示的图标都受 `--encoding` 支持时才显示图标。
* 也可作为库使用,包含系统剖析器模块、USB 描述符模块以及用于打印的 `display` 模块等。
* `--json` 输出,遵守过滤器和 `--tree` 设置。
* `--headers` 仅在请求时显示元数据,否则不占用空间。
* `--mask-serials` 可将序列号字符串设置为 '\*' 或随机化,以便在共享包含敏感序列号的转储文件时使用。
* 自动适应终端宽度。长度可变的字符串(如描述符)将被截断并以 '...' 表示。可通过配置选项 'no-auto-width' 禁用,并用 'max-variable-string-len' 定义固定最大长度。
* `cyme watch` 子命令,用于监视 USB 设备热插拔事件,并可实时编辑显示设置。可与所有全局标志一起使用。
* 支持 Linux、macOS 和 Windows 平台。
## 演示
* [watch 子命令的 YouTube 演示](https://youtu.be/ohRBrVBRolA)
# 安装
## 要求
预编译的二进制文件,请查看[发布页面](https://github.com/tuna-f1sh/cyme/releases)。预编译构建使用原生剖析后端,应无需额外依赖。
通过安装了 Rust 工具链的 crates.io 安装:`cargo install --locked cyme`。从本地克隆目录安装:`cargo install --locked --path .`。
### 包管理器
* [Homebrew 'cyme'](https://formulae.brew.sh/formula/cyme),它还会安装 man 手册页、补全文件以及 'libusb' 依赖项:
```
brew install cyme
```
* [Arch Linux 官方包](https://archlinux.org/packages/extra/x86_64/cyme/)
```
pacman -S cyme
```
* [Debian 包(作为发布的一部分)](https://github.com/tuna-f1sh/cyme/releases) —— 需要一个 Debian 维护者来完成此工作。
更多包管理器/软件包分发将陆续支持,如果您想在这方面帮忙,请随时创建 PR。
## 设置 `lsusb` 别名
如果希望创建 macOS 版本的 lsusb 或仅用此工具替代,可以在环境中创建一个带有 `--lsusb` 兼容性标志的别名:
`alias lsusb='cyme --lsusb'`
## Linux udev 信息
要在 Linux 上像 `lsusb` 一样获取正在使用的设备和接口驱动程序信息,可以在构建时使用 `--features udev` 特性 —— 这是一个默认特性。该特性使用 Rust crate [udevrs](https://crates.io/crates/udevrs) 获取信息。要使用 C FFI libudev 库,请使用 `--no-default-features --features udevlib`,这将使用 'libudev' crate。请注意,这需要在主机上安装 'libudev-dev'。
若要像 `lsusb` 一样从 udev hwdb 查找 USB ID,请使用 `--features udev_hwdb`。如果不使用 hwdb,`cyme` 将使用 'usb-ids' crate,其数据源与 hwdb 二进制数据相同,但捆绑的 hwdb 可能因自定义或更新时间不同而存在差异('usb-ids' 将是最新的)。
## 剖析器与特性标志
### 原生
使用原生 Rust [nusb](https://docs.rs/nusb/latest/nusb) 和 [udevrs](https://crates.io/crates/udevrs) 进行设备剖析:sysfs (Linux)、IOKit (macOS) 和 WinUSB。
自 2.0.0 起成为默认剖析器。使用 `--feature=native`(Linux 上为 'nusb' 和 'udevrs')或 `--feature=nusb` 手动指定。
### Libusb
使用 'libusb' 进行设备剖析。需要安装 [libusb 1.0.0](https://libusb.info):`brew install libusb`、`sudo apt install libusb-1.0-0-dev` 或您选择的包管理器。
在 2.0.0 之前是获取详细信息的默认特性。它是 `lsusb` 使用的剖析器,但由于 cyme 使用控制消息来收集相同信息,两者输出应无差异。如果希望使用 'libusb',请使用 `--no-default-features` 和 `--feature=libusb`,或同时使用 `--feature=ffi` 来支持 udevlib。
### macOS `system_profiler`
使用 macOS 的 `system_profiler SPUSBDataType` 命令来剖析设备。
在 2.0.0 之前是 macOS 系统提供基础信息的默认特性;'libusb' 用于打开设备以获取详细信息。如果使用默认的原生剖析器,现在不再使用它,但可以通过 `--system-profiler` 强制使用 —— 原生剖析器使用相同的 IOKit 后端,但由于不反序列化 JSON,速度更快。并且它始终能捕获总线编号,而 `system_profiler` 则不能。
# 用法
使用 `cyme --help` 获取基本用法,或查看 `man ./doc/cyme.1`。'./doc' 目录中也有自动补全脚本。
## 示例
### 树状视图
```
# 以树状格式列出所有 USB 设备和总线,默认显示块
cyme --tree
# 如上所述,但同时包含配置
cyme --tree --verbose
# 包括接口和端点 - 每个详细级别都进一步深入 USB 描述符树。此处使用短参数。
cyme --tree -vvv
# 以树状格式列出所有 USB 设备和总线,包含更多显示块、所有详细级别和标题以显示正在显示的内容
cyme --tree --more --headings
# 将树状结构导出为 JSON 文件 - --json 适用于所有选项
cyme --tree --verbose --json > tree.json
# 然后导入 JSON 文件以查看导出时的系统 USB 树状结构。所有 cyme 参数均可与此外部导入数据一同使用,如同分析数据。
cyme --from-json tree.json
```
### lsusb
```
# 类似 'lsusb' 列出所有 USB 设备和总线
cyme --lsusb
# lsusb 详细设备转储,包含所有描述符信息
cyme --lsusb --verbose
# lsusb 树状模式(可添加详细级别 [-v])
cyme --lsusb --tree
```
### 区块
查看 `cyme --help` 了解可用的区块。也可以省略参数值来显示选项。指定多个区块需要多个参数或 CSV 格式。默认情况下,提供的区块会添加到默认区块中。使用 `--block-operation` 更改此行为。
```
# 列出 USB 设备,显示更多块
cyme --more
# 在默认显示中添加 base-class 和 last-event 块,在总线显示中添加 host-controller-vendor
cyme --blocks base-class,last-event --bus-blocks host-controller-vendor
# 在接口块中添加 dev-path 和 mount-paths
cyme --interface-blocks dev-path,mount-paths
# 列出 USB 设备,指定显示块:name, vid, pid, serial, speed(可使用短参数 -b)
cyme --block-operation new --blocks name,vendor-id,product-id,serial -b speed
# 自定义其他块 - 此时可能使用配置更为便捷
cyme --blocks name --bus-blocks name --config-blocks name --interface-blocks class --endpoint-blocks number
# 使用 block-operation 通过参数块更改默认或配置块
cyme --block-operation remove --blocks serial
```
### 过滤
```
# 仅筛选 Apple 设备(vid:pid 为十六进制)
cyme -d 0x05ac
# 具体为 Apple 耳机,使用 '*' 掩盖序列号
cyme -d 05ac:8103 --mask-serials hide
# 筛选具有特定名称和类别的设备(不同标志表示逻辑与)
cyme --filter-name "Black Magic" --filter-class cdc-data
# 通过重复标志对两个供应商进行逻辑或(每次出现为一个单独的或筛选器)
cyme -d 0x05ac -d 0x1d50
# 对两个名称进行逻辑或
cyme --filter-name "Black Magic" --filter-name "FTDI"
# 使用 --filter-exclude 排除特定设备(KEY=VALUE,键:vidpid, name, serial, class, bus, number)
cyme --filter-exclude vidpid=05ac:8600
# 排除所有键盘同时仍按类别筛选
cyme --filter-class hid --filter-exclude name=Keyboard
# 用逗号分隔对在一个排除项内进行逻辑与;重复标志以对排除项进行逻辑或
cyme --filter-exclude vidpid=05ac:8600,name=Hub
```
过滤器也可以在配置文件中配置。示例可参考 './doc/cyme_example_filter_config.json' —— 这是一个演示所有字段的示例,并非建议直接使用!
### JSON - jq
```
# 为命名的 CDC ACM 设备查找 /dev/tty 设备(替换为 --filter-name 并配合 -d vid:pid 进行更具体筛选)
cyme --filter-class cdc-communications --filter-name 'esp' --json | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)'
# 查找大容量存储设备的挂载点
cyme --filter-class mass-storage --json | jq '.[] | {device_name: .name, devpaths: .extra.configurations[].interfaces[].devpaths, mounts: .extra.configurations[].interfaces[].mount_paths}'
# 仅转储新连接的设备(使用 cyme watch)
cyme --json watch | jq '.buses[] | .devices[]? | select( (.last_event | has("connected")))'
```
#### 函数
```
ttyvid() {
cyme --json --filter-class cdc-communications -d $1 | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)' | tr -d '"'
}
ttyname() {
cyme --json --filter-class cdc-communications --filter-name $1 | jq '.[] | (.extra.configurations[].interfaces[].devpaths[0]) | select(. != null)' | tr -d '"'
}
```
然后配合串口 IO 工具,根据 VID 或名称打开设备:`tio $(ttyname 'edbg')`
## Crate
若要作为库使用来剖析系统 USB 设备,该 crate 100% 有文档记录,请查阅 [docs.rs](https://docs.rs/cyme/latest/cyme/)。主要导入的有用模块是 [profiler](https://docs.rs/cyme/latest/cyme/profiler/index.html) 和 [usb](https://docs.rs/cyme/latest/cyme/usb/index.html)。
'examples/' 目录中也有一些示例,可通过 `cargo run --example filter_devices` 运行。它并非从头设计为 crate,但所有的 USB 描述符可能对高级 USB 剖析很有用。
## 配置
`cyme` 会在以下位置检查 'cyme.json' 配置文件:
* Linux: "$XDG\_CONFIG\_HOME/cyme 或 $HOME/.config/cyme"
* macOS: "$HOME/Library/Application Support/cyme"
* Windows: "{FOLDERID\_RoamingAppData}/cyme"
也可以通过 `--config` 指定。复制或参考 './doc/cyme\_example\_config.json' 进行配置。该文件本质上是默认参数;提供的参数会覆盖这些默认值。使用 `--debug` 查看其查找路径或是否未加载。
`cyme watch` 也可用于实时编辑显示设置,然后通过 'Ctrl-s' 将配置保存到默认位置。这可能是自定义显示区块最简单的方法。
### 自定义图标和颜色
请参阅 './doc/cyme\_example\_config.json' 了解如何定义图标的示例以及 [文档](https://docs.rs/cyme/latest/cyme/icon/enum.Icon.html)。如果不想定义任何新图标/颜色,配置中可以省略 "user"/"colours" 键。
图标按 User -> Default 顺序查找。对于设备:`Name` -> `VidPid` -> `VidPidMsb` -> `Vid` -> `UnknownVendor` -> `get_default_vidpid_icon`;对于类:`ClassifierSubProtocol` -> `Classifier` -> `UndefinedClassifier` -> `get_default_classifier_icon`。用户提供的颜色覆盖所有内部设置;如果缺少某个键,其值将为 `None`。
#### 图标不显示/显示为带问号的方框
内容复制自 [lsd](https://github.com/lsd-rs/lsd#icons-not-showing-up):为了让 `cyme` 能够显示图标,字体必须包含特殊的字形。您下载的大多数字体可能不包含这些字符。幸运的是,您可以使用 [NerdFont](https://www.nerdfonts.com/) 对大多数字体进行补丁以添加这些图标。或者,您可以直接从 [NerdFont 字体下载页面](https://www.nerdfonts.com/font-downloads) 下载已打补丁的您喜欢的字体版本。
以下是关于如何在 [macOS](https://github.com/Peltoche/lsd/issues/199#issuecomment-494218334) 和 [Android](https://github.com/Peltoche/lsd/issues/423) 上设置字体的指南。
要检查您使用的字体是否设置正确,请尝试在 shell 中运行以下代码片段,看看它是否[打印出一个文件夹图标](https://github.com/Peltoche/lsd/issues/510#issuecomment-860000306)。如果它打印出一个方框、问号或其他东西,那么您在设置字体或终端模拟器渲染字体的方式上可能存在问题。
```
echo $'\uf115'
```
如果不需要图标,请提供一个不包含任何 'icon\*' 块的自定义配置文件 —— 参见示例配置。或者,要仅使用所有字体支持的标准 UTF-8 字符(不使用私用区),请传递 `--encoding utf8` 和 `--icon auto`(默认值)。`--icon auto` 将在匹配的字符不被 `--encoding` 支持时丢弃图标块。
要完全不使用图标,请使用隐藏的 `--no-icons` 或 `--icon never` 参数。
# 已知问题
* 在 Linux 上,需要 `sudo` 权限才能打开和读取根集线器(root\_hub)字符串描述符,并且如果用户没有[权限](https://docs.rs/nusb/latest/nusb/#linux),可能需要对所有设备使用 sudo。然而,程序在没有这些权限的情况下也能正常工作,因为它会像 lsusb 一样使用 sysfs/hwdb/'usb-ids'。使用调试选项 `-z` 可查看哪些设备读取失败。环境变量 CYME_PRINT_NON_CRITICAL_PROFILER_STDERR 可用于将这些信息打印到标准错误输出。`--lsusb --verbose` 将始终向标准错误输出打印一条消息,以匹配 'lsusb' 的行为。
* 用户无法在 Apple 总线 (VHCI) 上打开特殊的非用户设备(例如 T2 芯片)。这些设备在使用 'native' 和 `system_profiler` 时仍会被列出,但使用 `--force-libusb` 则不会。它们不会打印详细信息,如果使用了 `--verbose`,会记录错误日志/如果使用了 `--lsusb` 则会打印错误。
标签:DNS解析, lsusb替代, Rust编程, USB总线, USB管理, WSL, 动态分析, 可视化界面, 嵌入式开发, 开源项目, 树状输出, 硬件监控, 硬件调试, 系统工具, 终端工具, 设备描述符, 通知系统