0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何知道设备控制设备的开流和关流动作

lhl545545 来源:漫谈嵌入式 作者:漫谈嵌入式 2022-09-30 10:27 次阅读

1.描述符布局

eb0c0d7e-3ff8-11ed-b1c7-dac502259ad0.png

如图为 bulk 传输描述符布局,相对于同步传输,批量传输只有一个可选择的配置,没有备用配置。

VideoControl :无变化

VideoStream:只有一个 bAlternateSetting(删除alt=1描述符)。同时支持bulk in 端点。

需要修改的地方:

staticstructusb_interface_descriptoruvc_streaming_intf_alt0={
.bLength=USB_DT_INTERFACE_SIZE,
.bDescriptorType=USB_DT_INTERFACE,
.bInterfaceNumber=UVC_INTF_VIDEO_STREAMING,
.bAlternateSetting=0,
.bNumEndpoints=1,/*alt0挂一个bulk端点*/
.bInterfaceClass=USB_CLASS_VIDEO,
.bInterfaceSubClass=UVC_SC_VIDEOSTREAMING,
.bInterfaceProtocol=0x00,
.iInterface=0,
};

端点描述符:

staticstructusb_endpoint_descriptoruvc_hs_streaming_ep={
.bLength=USB_DT_ENDPOINT_SIZE,
.bDescriptorType=USB_DT_ENDPOINT,
.bEndpointAddress=USB_DIR_IN,
.bmAttributes=USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize=512,
.bInterval=0,
};

2. 控制流程

根据USB规范可知,同步传输方式是只要带中带有同步端点的接口,系统会定时从设备中读取数据,无论设备中是否有数据。而如要停止数据的传输,只需要选中不带有同步端点的接口即可。

USB同步传输这种灵活的数据传输方式是依靠视频流接口的转换接口即我们常说的备份接口实现的。在默认情况下数据不传输时,视频数据流接口和备份接口ID为0,其它的备份接口是可根据视频数据传输的大小可按需选择。

我们知道,批量传输只有一个可选择的altsetting ,那么如何知道设备控制设备的开流和关流动作呢?

2.1 stream on

使用视频流接口的VS_COMMIT_CONTROL 提交给设备,让其以指定的数据格式进行数据采样。

eb45165a-3ff8-11ed-b1c7-dac502259ad0.png

2.2 stream off

关流操作,通过抓包可以看到,通过发送一个clear_halt 请求,来中断流的操作。

eba67e22-3ff8-11ed-b1c7-dac502259ad0.png

2.3 代码分析

基于 linux 4.14.281 内核版本:分析host 端uvc 开关流流程

drivers/media/usb/uvc/uvc_queue.c

开流操作:uvc_start_streaming

staticintuvc_start_streaming(structvb2_queue*vq,unsignedintcount)
{
structuvc_video_queue*queue=vb2_get_drv_priv(vq);
structuvc_streaming*stream=uvc_queue_to_stream(queue);
unsignedlongflags;
intret;

queue->buf_used=0;

ret=uvc_video_enable(stream,1);
if(ret==0)
return0;

spin_lock_irqsave(&queue->irqlock,flags);
uvc_queue_return_buffers(queue,UVC_BUF_STATE_QUEUED);
spin_unlock_irqrestore(&queue->irqlock,flags);

returnret;
}

关流操作:uvc_stop_streaming

staticvoiduvc_stop_streaming(structvb2_queue*vq)
{
structuvc_video_queue*queue=vb2_get_drv_priv(vq);
structuvc_streaming*stream=uvc_queue_to_stream(queue);
unsignedlongflags;

uvc_video_enable(stream,0);

spin_lock_irqsave(&queue->irqlock,flags);
uvc_queue_return_buffers(queue,UVC_BUF_STATE_ERROR);
spin_unlock_irqrestore(&queue->irqlock,flags);
}

重点关注:uvc_video_enable

/*
*Enableordisablethevideostream.
*/
intuvc_video_enable(structuvc_streaming*stream,intenable)
{
intret;

if(!enable){
uvc_uninit_video(stream,1);
if(stream->intf->num_altsetting>1){
usb_set_interface(stream->dev->udev,
stream->intfnum,0);
}else{
/*UVCdoesn'tspecifyhowtoinformabulk-baseddevice
*whenthevideostreamisstopped.Windowssendsa
*CLEAR_FEATURE(HALT)requesttothevideostreaming
*bulkendpoint,mimicthesamebehaviour.
*/
unsignedintepnum=stream->header.bEndpointAddress
&USB_ENDPOINT_NUMBER_MASK;
unsignedintdir=stream->header.bEndpointAddress
&USB_ENDPOINT_DIR_MASK;
unsignedintpipe;

pipe=usb_sndbulkpipe(stream->dev->udev,epnum)|dir;
usb_clear_halt(stream->dev->udev,pipe);
}

uvc_video_clock_cleanup(stream);
return0;
}

ret=uvc_video_clock_init(stream);
if(ret< 0)
  return ret;

 /* Commit the streaming parameters. */
 ret = uvc_commit_video(stream, &stream->ctrl);
if(ret< 0)
  goto error_commit;

 ret = uvc_init_video(stream, GFP_KERNEL);
 if (ret < 0)
  goto error_video;

 return 0;

error_video:
 usb_set_interface(stream->dev->udev,stream->intfnum,0);
error_commit:
uvc_video_clock_cleanup(stream);

returnret;
}

分析代码可知:

首先判断是否关流操作;

如果是,判断接口的可选配置是否大于1,如果大于1,发送usb_set_interface(intfnum,0) 关流,否则发送usb_clear_halt 请求;

如果是开流操作,发送commit 请求

然后初始化 video

/*
*Initializeisochronous/bulkURBsandallocatetransferbuffers.
*/
staticintuvc_init_video(structuvc_streaming*stream,gfp_tgfp_flags)
{
structusb_interface*intf=stream->intf;
structusb_host_endpoint*ep;
unsignedinti;
intret;

stream->sequence=-1;
stream->last_fid=-1;
stream->bulk.header_size=0;
stream->bulk.skip_payload=0;
stream->bulk.payload_size=0;

uvc_video_stats_start(stream);

if(intf->num_altsetting>1){
structusb_host_endpoint*best_ep=NULL;
unsignedintbest_psize=UINT_MAX;
unsignedintbandwidth;
unsignedintuninitialized_var(altsetting);
intintfnum=stream->intfnum;

/*Isochronousendpoint,selectthealternatesetting.*/
bandwidth=stream->ctrl.dwMaxPayloadTransferSize;

if(bandwidth==0){
uvc_trace(UVC_TRACE_VIDEO,"Devicerequestednull"
"bandwidth,defaultingtolowest.
");
bandwidth=1;
}else{
uvc_trace(UVC_TRACE_VIDEO,"Devicerequested%u"
"B/framebandwidth.
",bandwidth);
}

for(i=0;i< intf->num_altsetting;++i){
structusb_host_interface*alts;
unsignedintpsize;

alts=&intf->altsetting[i];
ep=uvc_find_endpoint(alts,
stream->header.bEndpointAddress);
if(ep==NULL)
continue;

/*Checkifthebandwidthishighenough.*/
psize=uvc_endpoint_max_bpi(stream->dev->udev,ep);
if(psize>=bandwidth&&psize<= best_psize) {
    altsetting = alts->desc.bAlternateSetting;
best_psize=psize;
best_ep=ep;
}
}

if(best_ep==NULL){
uvc_trace(UVC_TRACE_VIDEO,"Nofastenoughaltsetting"
"forrequestedbandwidth.
");
return-EIO;
}

uvc_trace(UVC_TRACE_VIDEO,"Selectingalternatesetting%u"
"(%uB/framebandwidth).
",altsetting,best_psize);

ret=usb_set_interface(stream->dev->udev,intfnum,altsetting);
if(ret< 0)
   return ret;

  ret = uvc_init_video_isoc(stream, best_ep, gfp_flags);
 } else {
  /* Bulk endpoint, proceed to URB initialization. */
  ep = uvc_find_endpoint(&intf->altsetting[0],
stream->header.bEndpointAddress);
if(ep==NULL)
return-EIO;

/*Rejectbrokendescriptors.*/
if(usb_endpoint_maxp(&ep->desc)==0)
return-EIO;

ret=uvc_init_video_bulk(stream,ep,gfp_flags);
}

if(ret< 0)
  return ret;

 /* Submit the URBs. */
 for (i = 0; i < UVC_URBS; ++i) {
  ret = usb_submit_urb(stream->urb[i],gfp_flags);
if(ret< 0) {
   uvc_printk(KERN_ERR, "Failed to submit URB %u "
     "(%d).
", i, ret);
   uvc_uninit_video(stream, 1);
   return ret;
  }
 }

 /* The Logitech C920 temporarily forgets that it should not be adjusting
  * Exposure Absolute during init so restore controls to stored values.
  */
 if (stream->dev->quirks&UVC_QUIRK_RESTORE_CTRLS_ON_INIT)
uvc_ctrl_restore_values(stream->dev);

return0;
}

从这段代码可以看出,如果altsetting 大于1 走同步传输,发送usb_set_interface(intfnum, altsetting) ,选择合适带宽配置。然后初始化同步传输管道。

否则,初始化 同步传输管道,提交传输。

3. 其他注意点

对比同步传输和批量传输我们可以发现,对于uvc 批量传输, 由于没有同步传输类似的多个可选配置,所以没法灵活控制开流关流操作。特别是在linux 平台下,要切换不同的格式和分辨率的时候没有同步传输方便。

故,笔者觉得同步传输适合传固定数据,或者对usb camera 做中转使用比较合适。

对于批量传输如果能充分发送usb 吞吐量,(USB2.0)一个微帧传输13个packet,理论带宽将近50MB/s, 笔者实际测试能达到47MB/s,对于YUYV图像能够极大提高帧率。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 接口
    +关注

    关注

    33

    文章

    7635

    浏览量

    148451
  • 数据传输
    +关注

    关注

    9

    文章

    1525

    浏览量

    63560
  • 控制设备
    +关注

    关注

    0

    文章

    68

    浏览量

    10576

原文标题:UVC 批量传输技术探讨

文章出处:【微信号:漫谈嵌入式,微信公众号:漫谈嵌入式】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    浅谈剩余电流动作继电器的在低压配电系统中的应用

    和接地短路而引起火灾等安全隐患和经济损失。因此创新智能漏电保护装置已迫在眉睫。而剩余电流动作继电器用来防止以上事故是一种较好的保护装置,其主要作用是保护人身免受电击伤亡、防止电气设备或线路漏电大而
    发表于 01-11 16:33

    浅谈剩余电流动作断路器在钢铁厂供电系统改造中的应用

    【摘要】 钢铁厂为了实现节能降碳、安全运行,在不断升级改造现有生产设备。针对钢铁厂改造中对剩余电流动作断路器的设计应用方案进行探讨,解析了剩余电流动作断路器在电网供电系统中对设备和线路
    发表于 01-11 16:45

    使用Cyusb3014芯片进行Type-C/短路测试,计算机无法识别USB设备的原因?

    你好,我正在使用 Cyusb3014 芯片进行 Type-C /短路测试。 我用芯片来分配信号,还有一个开关可以选择是使用数据线还是测试电缆。 插上 Type-C 后,我首先将数据导入测试电缆
    发表于 02-27 07:20

    DFP 防 偏

    DFP 防 偏 概述:●通用的安装设计可使防偏开关随意安装在输送机纵梁顶部或底部。●坚固的铸铝外壳,特殊的环境可选择特殊的表面处理。●整体式盖板易于接线及调整,不需拆除动作杆就的可拆卸盖板
    发表于 07-26 11:46

    谁可以做安卓的APP,然后接合单片机控制设备运转

    谁可以做安卓的APP,然后接合单片机控制设备运转就是我想用手机无线控制我们的设备设备一共有1.前进,后退2.
    发表于 05-21 16:52

    求教:怎么用按键控制电源的

    求教:怎么用按键控制电源的,现在需要用按键去控制电源的开关,按一下,再按一下,电源接断开了。。。最好有电路图{:1:}PCB打样找华
    发表于 07-15 21:16

    求如何用NI 6002 的电压输出通道控制外围设备动作,如控制24V继电器合!

    求如何用NI 6002 的电压输出通道控制外围设备动作,如控制24V继电器合!
    发表于 03-02 18:38

    控制两个喇叭

    怎样控制两个喇叭中某一个喇叭的,简单方式,不是控制电源那种方法。
    发表于 11-13 14:09

    请问如何控制DAQ助手的

    怎么通过条件结构控制DAQ助手的,就是运行程序之后点开始按钮才开始采集数据
    发表于 11-04 20:12

    转帖 剩余电流动作保护器(RCD)的分类、作用、以及接线方式!

    剩余电流动作保护装置是具有漏电保护功能的开关设备,IEC标准定名为剩余电流动作保护装置,缩写为RCD,我国标准将其明确为当电气线路和电气设备发生单相接地故障时,利用这个剩余电流来
    发表于 10-23 10:56

    剩余电流动作继电器在浴室中的应用

    一种能够在设备、线路等发生漏电时及时切断电源的保护装置,这在高湿的浴室环境里使用显得尤为重要。  关键词:浴室;安全用电;剩余电流动作继电器  引言:  随着物质文化生活水平的提高,人们对自己生活
    发表于 01-21 15:31

    剩余电流动作继电器的应用探讨

    继电器依据的标准是GB/T 22387-2016 《剩余电流动作继电器》和GB/T 13955-2017 《剩余电流动作保护装置安装和运行》,两者都是推荐性标准。对于某些人和设备重要的场所,应当装设
    发表于 01-22 14:24

    剩余电流动作继电器的应用探讨

    场所。 现在剩余电流动作继电器依据的标准是GB/T 22387-2016 《剩余电流动作继电器》和GB/T 13955-2017 《剩余电流动作保护装置安装和运行》,两者都是推荐性标准。对于某些人和
    发表于 01-04 15:16 496次阅读

    剩余电流动作时间要求是什么呢?

    剩余电流动作时间要求是什么呢? 剩余电流动作时间要求是指在电路中存在着出现短路或接地故障时,电器设备的保护措施能够及时地切断电路的时间间隔。这个时间间隔的要求是为了保证电器设备和人员的
    的头像 发表于 12-25 15:12 277次阅读

    浅谈剩余电流动作保护器在接地系统中的应用

    保护器或不规范地接线,会使剩余电流动作保护器误动或拒动,甚至引起人身触电和电气火灾事故。从剩余电流动作保护器工作原理出发,着重于用电设备的电流矢量分析与计算,阐述剩余电流动作保护器在低
    的头像 发表于 02-19 14:21 118次阅读
    浅谈剩余电<b class='flag-5'>流动作</b>保护器在接地系统中的应用