项目自定义 Function:f_bytrans 与 f_audio_raw

项目自定义 Function:f_bytrans 与 f_audio_raw

本树function/Makefile第 53-56 行无条件以obj-m编译两个 2024 年新增的私有 Function,上游内核不存在,是本项目(YPC Encode)的扩展。两者结构相似:ConfigFS function + 字符设备 + kfifo,用户态经/dev节点与 Host 交换数据。

1. f_bytrans(字节透传,/dev/msgtrans*

1.1 USB 接口

单接口 Vendor Specific(class 0xFF),3 个端点(f_bytrans.c:63):

端点 FS HS SS
Bulk IN 64B 512B 1024B + burst 15
Bulk OUT 64B 512B 1024B + burst 15
Interrupt IN 64B/interval16 512B/interval4 1024B/interval2

Interrupt IN 用于向 Host 上报RX_FIFO_FULL(0xA0)/TX_FIFO_FULL(0xA1)流控事件(宏定义 36-37 行)。

1.2 核心结构与资源

struct f_bytrans(213 行):

  • tx_fifo/rx_fifo:各 512KB kfifo(FIFO_SIZE=524288);
  • send_thread:内核线程bytrans_send,从 tx_fifo 取数据组 bulk IN 请求(847 行);
  • wq:workqueue 处理 bulk OUT completion 入 rx_fifo;
  • 包缓冲MAX_PACKET_SIZE=1024、每 URB MAX_PACKET_COUNT=32事务;
  • 字符设备:cdev_add于 901 行,device_create于 908 行,节点名msgtrans<minor>,class bytrans,minor 由 IDA 分配。

1.3 数据路径

1
2
3
4
5
6
Host -> bulk OUT -> bytrans_bulk_out_complete -> workqueue -> rx_fifo
-> 用户 read(/dev/msgtransN) (空时阻塞于 recv_wait)

用户 write(/dev/msgtransN) -> tx_fifo -> send_thread 唤醒
-> 组request queue到 bulk IN -> Host
FIFO 满 -> interrupt IN 通知 Host 暂停

1.4 生命周期与注册

  • bytrans_alloc_inst_fixed()(989 行)创建 instance 并初始化 configfs item(item_ops 966 行、attrs 977 行);
  • bytrans_alloc()(787 行)创建 function,function.name = "bytrans"(809 行);
  • DECLARE_USB_FUNCTION_INIT(bytrans, ...)(1011 行)注册,ConfigFS 用法:
1
2
mkdir functions/bytrans.0
ln -s functions/bytrans.0 configs/c.1/
  • 释放路径bytrans_free_inst()(778 行);unbind 时kthread_stop(937 行)。

1.5 审阅要点(潜在风险)

  • send_thread/workqueue 与set_alt/disable并发:断开时在途 request 与 kfifo 状态需要严格同步,注意online标志的内存序;
  • 代码含大量BYTRANS_DEBUG pr_info,量产应降级;
  • FIFO 满策略依赖 Host 配合中断通知,Host 端不理会时会丢数据或阻塞;
  • 字符设备无并发 open 保护说明,多进程同时读写语义未定义,应用侧应单实例使用。

2. f_audio_raw(原始音频,/dev/audio_raw.*

2.1 设计动机

绕开 UAC 标准协议栈,用 Vendor Specific 接口 + isochronous 端点直接传原始音频字节,Host 侧配套私有驱动/应用。相比 f_uac2 省去 ALSA 和 class request 复杂度,但失去标准 Host 兼容性。

2.2 USB 接口

单接口两个 alternate setting(116-137 行):

  • alt 0:无端点(空闲);
  • alt 1:isoc IN + isoc OUT 各一(FS 1023B/interval1,HS 1024B/interval4,SS 1024B/interval2 加 companion)。

audio_raw_set_alt()(687 行)在 alt 1 时使能端点、预队 OUT 请求并置online/rx_enabled/tx_enabled

2.3 数据面

struct f_audio_raw(48 行起):

  • fifo_rx:64KB kfifo(FIFO_SIZE37 行);
  • IN/OUT 各MAX_URBS=32个预分配 request;
  • 读写超时WRITE_TIMEOUT_MS/READ_TIMEOUT_MS = 5000
1
2
3
4
5
6
Host -> isoc OUT complete (274行) -> kfifo_in(fifo_rx) -> read_wait唤醒
用户 read (325行): 数据不足则等待(kfifo_len>=len 或 offline)
kfifo_to_user (360行)
用户 write (366行): 取空闲 in_req 填数据 queue 到 isoc IN
无空闲request时等待 write_wait
poll (453行): fifo_rx 有数据 -> EPOLLIN;有空闲URB -> EPOLLOUT

isoc 无重传:OUT 侧 fifo 满时新数据直接丢弃(281 行仅打 debug),IN 侧欠载表现为 Host 收流中断。实时性依赖应用及时消费/供给。

2.4 字符设备与实例

  • class audio_raw(862 行创建),chrdev region 256 个 minor(873 行);
  • 每实例节点名audio_raw.<instance_id>(964 行),function.name = "audio_raw"(968 行);
  • audio_raw_alloc_inst()(847 行)分配实例,DECLARE_USB_FUNCTION_INIT于 993 行;
  • ConfigFS:mkdir functions/audio_raw.0后同常规流程。

2.5 审阅要点

  • 文件为新写代码,含中文注释和 debug 日志,风格与上游不一致(缩进混用),合入主线前需清理;
  • offline 竞争:read/write在等待中检查!fa->online退出(352/398 行),但 completion 与 disable 的时序仍需重点测试拔线场景;
  • isoc 带宽在 HS interval4 下约 1024B/500µs≈2MB/s,设计音频格式时须核对是否够用;
  • OUT 丢弃策略意味着不能承载不容忍丢包的数据,只适合音频类容错流。

3. 与标准方案的选型对照

需求 建议
标准 Host 免驱音频 f_uac1/f_uac2
私有低延迟音频流、自控协议 f_audio_raw(本树方案)
可靠字节/消息通道 f_bytrans(bulk,有流控) 或 FunctionFS
用户态完整协议栈 FunctionFS

两个自定义 function 均为obj-m,部署需确认模块随镜像安装并在组装 gadget 前 modprobe。

文章互动

阅读 --

留言

0 条留言

正在加载留言…