avatar Nihil

Nichts Hsu

  • 首页
  • 子域
  • 分类
  • 标签
  • 归档
  • 关于
首页 抓包查看 UVC 设备选择的分辨率与帧率
文章

抓包查看 UVC 设备选择的分辨率与帧率

发表于 2023/05/29 更新于 2024/04/26
作者 Nichts Hsu
3 分钟阅读

使用工具: Bus Hound, USB Device Tree Viewer

打开 Bus Hound,转到 Devices 选项卡,在设备列表中找到想抓包的 UVC 设备,勾选其 UVC interface。如果你不确定,可以把全部勾上,不影响:

Bus Hound Devices

通常,Video 帧数据通过 ISOC 传输,为了避免巨量的帧数据影响我们抓包,我们可以在 Settings 选项卡里把 ISOC 取消勾选。当然,一个更简单的方法是,除了必要的 CTL 和 OUT 以外其他的全部取消勾选:

Bus Hound Settings

回到 Capture 选项卡,点击右下角的 Run 按钮开始抓包,然后打开使用该 UVC 设备的程序,抓取 USB 数据包。

在抓到的 USB 数据包中,我们去寻找以 21 01 00 02 开头的 CTL 包以及它紧邻的 OUT 包:

Bus Hound Capture

该 CTL 包以下面的方式解析(注:都是小端序,即,先低字节,后高字节):

bmRequestType bRequest wValue wIndex wLength
0x21 0x01 0x00 0x02 0x01 0x00 0x1a 0x00
  1. bmRequestType 指示请求的方向(Direction),类型(Type)及接收者(Recipient),0x21 代表:Direction = Host to Device, Type = Class, Recipient = Interface。
  2. bRequest 指示请求的内容,0x01 代表 SET_CUR,即 Set Current 的缩写,设置当前属性。
  3. wValue 对于 UVC 而言,其低位必须为 0,高位用于指示 CS(Control Selector)。0x02 对应的 CS 为 VS_COMMIT_CONTROL,用于提交所选择的 UVC 属性(这些属性在随后的 OUT 包中配置)。
  4. wIndex 高位为 0,低位指示目标 interface 的 bInterfaceNumber,如果 UVC 设备有多个可选相机,可以以此进行区分。
  5. wLength 指示尾随的 OUT 包的大小,0x1a 即 26 字节。

之后尾随的 OUT 包的数据格式,可以在规格书 UVC 1.5 Class specification 中的 Table 4-75 Video Probe and Commit Controls 找到完整定义,我们这边不解释它所有字段的含义,仅介绍我们所感兴趣的那几个:

  1. 第三个字节 0x02,表示所选择的 UVC 格式类型描述符的 bFormatIndex,我们通过 USB Device Tree Viewer 可以找到该格式类型为 MJPEG:

    Device Tree View Format

  2. 第四个字节,0x04,表示所选择的 UVC 帧类型描述符的 bFrameIndex,我们通过 USB Device Tree Viewer 可以找到 MJPEG 格式对应的该帧类型为 1920x1080 分辨率:

    Device Tree View Frame

  3. 第五~八字节,0x15 0x16 0x05 0x00,表示所选的 dwFrameInterval,即帧间隔(单位是 100 ns)。由于是小端序,也就是说实际值是 0x00051615 即 333333 * 100ns,则对应的帧率为 30 帧。

教程, USB
usb 教程 uvc 抓包
本文由作者按照 CC BY 4.0 进行授权
分享

最近更新

  • 『I Wanna』 Best Bye To 2016
  • [译] Rust 中的内联
  • [Rust] 幽灵索引类型与匿名结构体
  • [C++] 深入了解左值与右值
  • Android.bp 中启用 openmp
外部链接
  • 996.icu
  •  此博客的 Github 仓库
  •  Olimi 的个人博客

相关文章

2022/01/11

Git 从基础到进阶

前言 Git 是什么 想象这么一个场景,你和你的几个同事一起开发一个应用,假设同事 A 修改了代码 1,同事 B 修改了代码 2,你自己修改了代码 3,要如何将你们的修改安全、准确地同步到所有人的电脑上?如果有一天,应用突然运行不了了,你尝试 debug 无果,想要回退到上一次能够正常运行的代码版本,你要如何操作? 这就是为什么我们需要版本控制工具。它们对代码的提交和修改进行纪录,方便...

2021/09/15

Shell 中的管道、重定向、进程替换

管道 相信绝大部分 Linux 用户对管道(Pipe)都不陌生,其语法是: command1 | command2 它的作用是将 command1 的标准输出作为 command2 的标准输入来使用。一个非常典型的例子是 grep,相信大部分人都有使用过形如 command | grep xxx 的命令。 管道的两个命令分别在两个不同的子 shell 中执行,并且没有规定哪个...

2021/06/07

Rust 中的闭包递归与 Y 组合子

λ 函数递归 λ 函数也即匿名函数,在 Rust 中体现为闭包(Closure)。在一些语言中,你可以简单地在 λ 函数内调用自己实现递归,例如在 JavaScript 中实现一个阶乘: fact = n => { if (n == 0) return 1; else return n * fact(n - 1); } console.log(fact(5)) //...

C++ Coroutine VS Rust Async

[C++] 深入了解左值与右值

© 2024 Nichts Hsu. 保留部分权利。

本站采用 Jekyll 主题 Chirpy

热门标签

编程语言 教程 rust c++ android c++20 usb 翻译 linux qt

发现新版本的内容。