惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MongoDB | Blog
MongoDB | Blog
J
Java Code Geeks
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
DataBreaches.Net
腾讯CDC
GbyAI
GbyAI
I
InfoQ
博客园 - Franky
G
Google Developers Blog
Last Week in AI
Last Week in AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
Visual Studio Blog
Vercel News
Vercel News
博客园_首页
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium
V
V2EX
T
The Blog of Author Tim Ferriss
M
MIT News - Artificial intelligence
雷峰网
雷峰网
H
Hackread – Cybersecurity News, Data Breaches, AI and More
大猫的无限游戏
大猫的无限游戏
The GitHub Blog
The GitHub Blog

博客园 - sheldon_blogs

RK3588 Android12 rknpu驱动升级及通过fastboot更新 Android设备搭建本地RTSP服务器(基于live555) Android上玩转TUN设备及rtsp传输 Android14 RK3588平台内核异常中断占用CPU问题排查 Android平台移植stress-ng工具及使用 Android OTA的两种方式:Non-A/B(recovery)和A/B系统升级 Android的USB网络共享功能 Linux修改Swap分区大小及使用优先级 Android开放配件 (AOA) 协议 Android(S)系统属性服务详解 Android12 双屏异显/异触流程分析 Android Webview 调试总结 RK3588 Android12 编译打包私有ext4格式vendor.img并挂载到新增vendor_private分区 C++提取字符串中的整数 Android UVC Camera H.265帧序错乱问题 RK3588 Android12 一个固件兼容多个板型方案 全志A133 Android10 Display框架实践 Android编译脚本添加kernel编译选项传入宏定义 UAC实例分析-USB音响 Android USB之复合设备(gadget)详解
Android设备之间UVC Gadget bulk模式无法正常打开问题
sheldon_blogs · 2024-09-03 · via 博客园 - sheldon_blogs

平台:RK3588
Android版本:12
内核版本:Linux 5.10.66

问题: 通过usb gadget枚举uvc设备后,使用bulk传输,连接windows PC可用正常打开预览,连接到另外Android Host设备无法正常打开。如果使用isochronous方式传输则都正常。

分析:连接到PC(windows)上可以正常出图,但是连接到另外一个RK3588设备,可以正常识别到设备,也可以用v4l2-ctl读到正常配置信息,但是打开对应video节点取流时阻塞住了,从另一端RK3588(device)查看uvc gadget应用端 ioctl执行VIDIOC_STREAMON报错: UVC: Unable to start streaming No such device (19). 另外接了一个bulk传输的usb摄像头到rk3588上是正常的,说明问题出在uvc gadget device驱动。

既然报错在VIDIOC_STREAMON,则从驱动代码中对应方法入手排查:

kernel-5.10/drivers/usb/gadget/function/uvc_v4l2.c

static int
uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
{
        struct video_device *vdev = video_devdata(file);
        struct uvc_device *uvc = video_get_drvdata(vdev);
        struct uvc_video *video = &uvc->video;
        int ret;

        //通过打印知道在此处判断不是UVC_STATE_CONNECTED状态就直接返回错误
        if (uvc->state != UVC_STATE_CONNECTED)
            return -ENODEV;

        /* Enable UVC video. */
        ret = uvcg_video_enable(video, 1);
        if (ret < 0)
                return ret;

        /*
         * Alt settings in an interface are supported only
         * for ISOC endpoints as there are different alt-
         * settings for zero-bandwidth and full-bandwidth
         * cases, but the same is not true for BULK endpoints,
         * as they have a single alt-setting.
         *
         * For ISOC endpoints, Complete the alternate setting
         * selection setup phase now that userspace is ready
         * to provide video frames.
         */
        if (!usb_endpoint_xfer_bulk(video->ep->desc)) {
                uvc_function_setup_continue(uvc);
        }

        uvc->state = UVC_STATE_STREAMING;

        return 0;
}

在以上代码段加打印调试知道是此时stream on走到这里时 uvc->state 值已经是 UVC_STATE_STREAMING,直接返回 -EINVAL,而对比isoc传输stream on时是UVC_STATE_CONNECTED状态,然后通过连接不同host的log对比发现bulk模式连接 Android设备上的时候就会走了1次 uvc_function_set_alt,然后stream on时又会执行一次,  此时就已经把 uvc->state 改成了 UVC_STATE_STREAMING:

对应源码中就是在此处更改了uvc->state的值:

kernel-5.10/drivers/usb/gadget/function/f_uvc.c

以至于后面走到uvc_v4l2_streamon时就判断uvc->state != UVC_STATE_CONNECTED 直接  return -ENODEV。

解决方法:修改uvc_v4l2_streamon中针对bulk模式时的判断逻辑,在 uvc->state == UVC_STATE_DISCONNECTED 才 return -ENODEV。

--- a/kernel-5.10/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/kernel-5.10/drivers/usb/gadget/function/uvc_v4l2.c
@@ -200,8 +200,15 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
        if (type != video->queue.queue.type)
                return -EINVAL;

-       if (uvc->state != UVC_STATE_CONNECTED)
-               return -ENODEV;
+       //sheldon add begin: for bulk mode
+       if (!usb_endpoint_xfer_bulk(video->ep->desc)) {
+               if (uvc->state != UVC_STATE_CONNECTED)
+                       return -ENODEV;
+       } else {
+               if (uvc->state == UVC_STATE_DISCONNECTED)
+                       return -ENODEV;
+       }
+       //sheldon add end

具体连接Android平台为什么走的流程不一样还不清楚,可能和 https://www.usbzh.com/article/detail-166.html 描述的类似,连接Linux主机时就进行了参数配置,而Windows在打开摄像头的时候才进行相关参数的获取,所以UVC设备在连接Windows和Linux时是有区别的。