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

1.描述符布局
如图为 bulk 传输描述符布局,相对于同步传输,批量传输只有一个可选择的配置,没有备用配置。
videocontrol :无变化
videostream:只有一个 balternatesetting(删除alt=1描述符)。同时支持bulk in 端点。
需要修改的地方:
static struct usb_interface_descriptor uvc_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,};  
端点描述符:
static struct usb_endpoint_descriptor uvc_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 提交给设备,让其以指定的数据格式进行数据采样。
2.2 stream off
关流操作,通过抓包可以看到,通过发送一个clear_halt 请求,来中断流的操作。
2.3 代码分析
基于 linux 4.14.281 内核版本:分析host 端uvc 开关流流程
drivers/media/usb/uvc/uvc_queue.c
开流操作:uvc_start_streaming
static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count){ struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; int ret; queue->buf_used = 0; ret = uvc_video_enable(stream, 1); if (ret == 0)  return 0; spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, uvc_buf_state_queued); spin_unlock_irqrestore(&queue->irqlock, flags); return ret;}  
关流操作:uvc_stop_streaming
static void uvc_stop_streaming(struct vb2_queue *vq){ struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; 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
/* * enable or disable the video stream. */int uvc_video_enable(struct uvc_streaming *stream, int enable){ int ret; if (!enable) {  uvc_uninit_video(stream, 1);  if (stream->intf->num_altsetting > 1) {   usb_set_interface(stream->dev->udev,       stream->intfnum, 0);  } else {   /* uvc doesn't specify how to inform a bulk-based device    * when the video stream is stopped. windows sends a    * clear_feature(halt) request to the video streaming    * bulk endpoint, mimic the same behaviour.    */   unsigned int epnum = stream->header.bendpointaddress        & usb_endpoint_number_mask;   unsigned int dir = stream->header.bendpointaddress      & usb_endpoint_dir_mask;   unsigned int pipe;   pipe = usb_sndbulkpipe(stream->dev->udev, epnum) | dir;   usb_clear_halt(stream->dev->udev, pipe);  }  uvc_video_clock_cleanup(stream);  return 0; } ret = uvc_video_clock_init(stream); if (ret ctrl); if (ret udev, stream->intfnum, 0);error_commit: uvc_video_clock_cleanup(stream); return ret;}  
分析代码可知:
首先判断是否关流操作;
如果是,判断接口的可选配置是否大于1,如果大于1,发送usb_set_interface(intfnum,0) 关流,否则发送usb_clear_halt 请求;
如果是开流操作,发送commit 请求
然后初始化 video
/* * initialize isochronous/bulk urbs and allocate transfer buffers. */static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags){ struct usb_interface *intf = stream->intf; struct usb_host_endpoint *ep; unsigned int i; int ret; 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) {  struct usb_host_endpoint *best_ep = null;  unsigned int best_psize = uint_max;  unsigned int bandwidth;  unsigned int uninitialized_var(altsetting);  int intfnum = stream->intfnum;  /* isochronous endpoint, select the alternate setting. */  bandwidth = stream->ctrl.dwmaxpayloadtransfersize;  if (bandwidth == 0) {   uvc_trace(uvc_trace_video, device requested null     bandwidth, defaulting to lowest.);   bandwidth = 1;  } else {   uvc_trace(uvc_trace_video, device requested %u     b/frame bandwidth., bandwidth);  }  for (i = 0; i num_altsetting; ++i) {   struct usb_host_interface *alts;   unsigned int psize;   alts = &intf->altsetting[i];   ep = uvc_find_endpoint(alts,    stream->header.bendpointaddress);   if (ep == null)    continue;   /* check if the bandwidth is high enough. */   psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);   if (psize >= bandwidth && psize desc.balternatesetting;    best_psize = psize;    best_ep = ep;   }  }  if (best_ep == null) {   uvc_trace(uvc_trace_video, no fast enough alt setting     for requested bandwidth.);   return -eio;  }  uvc_trace(uvc_trace_video, selecting alternate setting %u    (%u b/frame bandwidth)., altsetting, best_psize);  ret = usb_set_interface(stream->dev->udev, intfnum, altsetting);  if (ret altsetting[0],    stream->header.bendpointaddress);  if (ep == null)   return -eio;  /* reject broken descriptors. */  if (usb_endpoint_maxp(&ep->desc) == 0)   return -eio;  ret = uvc_init_video_bulk(stream, ep, gfp_flags); } if (ret quirks & uvc_quirk_restore_ctrls_on_init)  uvc_ctrl_restore_values(stream->dev); return 0;}  
从这段代码可以看出,如果altsetting 大于1 走同步传输,发送usb_set_interface(intfnum, altsetting) ,选择合适带宽配置。然后初始化同步传输管道。
否则,初始化 同步传输管道,提交传输。
3. 其他注意点
对比同步传输和批量传输我们可以发现,对于uvc 批量传输, 由于没有同步传输类似的多个可选配置,所以没法灵活控制开流关流操作。特别是在linux 平台下,要切换不同的格式和分辨率的时候没有同步传输方便。
故,笔者觉得同步传输适合传固定数据,或者对usb camera 做中转使用比较合适。
对于批量传输如果能充分发送usb 吞吐量,(usb2.0)一个微帧传输13个packet,理论带宽将近50mb/s, 笔者实际测试能达到47mb/s,对于yuyv图像能够极大提高帧率。


四川瞄准电子信息产业万千百亿工程 坐实四川第一支柱电子信息产业
InfiniiVision 2000 X系列示波器的功能特性及应用范围
英飞凌将斥资2020万美元在新加坡建立全球首个人工智能中心
缺陷诱导致密非晶/晶相异质结实现快速稳定储钠
据Gartner预测:2020年世界半导体晶圆代工市场预计为680亿美元
如何知道设备控制设备的开流和关流动作
微型空气监测系统的特点是怎样的
ADI发表同级产品中最具效率的交换式稳压器
无人机常用的可靠性测试有哪些_无人机常用的6大可靠性测试盘点
SK海力士完成业内首款多堆栈176层4D闪存集成PUC技术研发
印度政府提供关税优惠吸引苹果供应链
GIPS宣布任命Anton Schwarz为全球销售副总裁
SJ MOSFET的应用及与SiC和GaN的比较
OC门电路和OD门电路原理讲解
pcb layout中电磁兼容设计的基本内容和要求
MAX3420E系统调试
研究人员开发出能机器人户外导航的声音定位系统
败家汽车音响篇 福特翼虎改装芬朗HI-FI乌托邦
车厘子高新技术企业申请顺利通过啦!
全面剖析UML(下)