0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

UVC bulk傳輸實現思路

漫談嵌入式 ? 來源: 漫談嵌入式 ? 2023-09-25 10:00 ? 次閱讀

前段時間有個讀者咨詢UVC bulk 傳輸實現,接著這個機會重新梳理一遍UVC bulk 傳輸實現思路,同時對比ISO 與 Bulk 實現不同。有關bulk 傳輸實現請先看前文

閱讀此文前提:假設讀者,已知曉UVC 協(xié)議,以及UVC 設備驅動框架

1. 描述符布局

1.1 ISO 傳輸

1525fe18-5ae6-11ee-939d-92fbcf53809c.png

ISO 傳輸模式下的描述符布局如上圖所示:

一個配置

兩個接口:Video Control / Video Stream

接口0:VideoControl。處理 UVC CT/PU/XU 等處理,主要用來控制接口1:VideoStream。處理UVC 視頻流控制。

一個VideoControl 可以關聯一個或者多個流接口。每個流接口下面,關聯2個多或者多個接口配置。

對于ISO 傳輸,流接口下有多個備用接口,用來控制視頻流的傳輸。一般用alt0 關流,altx 開流。

1.2 BULK 傳輸

153f1eca-5ae6-11ee-939d-92fbcf53809c.png

BULK 傳輸模式下的描述符布局如上圖所示:

一個配置

兩個接口:Video Control / Video Stream

接口0:VideoControl。處理 UVC CT/PU/XU 等處理,主要用來控制接口1:VideoStream。處理UVC 視頻流控制。

對于BULK 傳輸, 與ISO 模式最大的不同,是流接口只有一個alt0 接口配置。故,對其視頻流的控制流程,相比較ISO 模式比較復雜一些。

2. 控制流程

2.1 ISO 傳輸

根據USB規(guī)范可知,同步傳輸方式是只要選中中帶有同步端點的接口,系統(tǒng)會定時從設備中讀取數據,無論設備中是否有數據。而如要停止數據的傳輸,只需要選中不帶有同步端點的接口即可。

USB同步傳輸這種靈活的數據傳輸方式是依靠視頻流接口的轉換接口即我們常說的備份接口實現的。

Stream ON:

155189e8-5ae6-11ee-939d-92fbcf53809c.png

Stream OFF:

1578d534-5ae6-11ee-939d-92fbcf53809c.png

整個視頻流的控制流程(開流/關流),可以在設備收到set_alt1/0 后進行處理。

2.2 BULK 傳輸

從描述符上分析 UVC 的 bulk 傳輸只有一個備用接口。故無法通過ISO 模式下通過備用接口進行開關流控制。

StreamOn:

15963732-5ae6-11ee-939d-92fbcf53809c.png

StreamOff

15c6f084-5ae6-11ee-939d-92fbcf53809c.png

通過抓包對比發(fā)現,開流過程通過uvc probe 與commit 流程處理。關流過程主機會下發(fā)一個clear_halt 請求。在clear_halt 請求里面做關流的后處理。

通過對比發(fā)現,對于ISO 傳輸,針對UVC 的設備描述修改基本不大,難處理的是UVC 的控制流程,特別是視頻流的處理,接下來我們會以linux 平臺介紹如何在iso 基礎上修改為 bulk 模式

3. 源碼分析

我們以linux 平臺舉例,其他平臺只要熟悉uvc 底層協(xié)議,即可快速遷移。

3.1 host 端

源碼位置:driver/media/uvc/uvc_queue.c

uvc 使能:

intuvc_video_enable(structuvc_streaming*stream,intenable)
{
intret;

if(!enable){
...
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.
*/

......
usb_clear_halt(stream->dev->udev,pipe);
}
......
return0;
}

/*Committhestreamingparameters.*/
ret=uvc_commit_video(stream,&stream->ctrl);
if(retdev->udev,stream->intfnum,0);
error_commit:
uvc_video_clock_cleanup(stream);

returnret;
}

StreamOn:

uvc_start_streaming()//
ret=uvc_video_enable(stream,1);

StreamOff:

uvc_stop_streaming();
uvc_video_enable(stream,0);

從host 端源碼分析和我們猜想得到了印證:

開流發(fā)送commit 請求

關流發(fā)送clear_halt 請求

視頻傳輸:源碼參考:driver/media/usb/uvc_video.c

//usbcomplete中斷
staticvoiduvc_video_complete(structurb*urb)
{
structuvc_streaming*stream=urb->context;
structuvc_video_queue*queue=&stream->queue;
structuvc_buffer*buf=NULL;
unsignedlongflags;
intret;

switch(urb->status){
case0:
break;

default:
uvc_printk(KERN_WARNING,"Non-zerostatus(%d)invideo"
"completionhandler.
",urb->status);
/*fallthrough*/
case-ENOENT:/*usb_kill_urb()called.*/
if(stream->frozen)
return;
/*fallthrough*/
case-ECONNRESET:/*usb_unlink_urb()called.*/
case-ESHUTDOWN:/*Theendpointisbeingdisabled.*/
uvc_queue_cancel(queue,urb->status==-ESHUTDOWN);
return;
}

spin_lock_irqsave(&queue->irqlock,flags);
if(!list_empty(&queue->irqqueue))
buf=list_first_entry(&queue->irqqueue,structuvc_buffer,
queue);
spin_unlock_irqrestore(&queue->irqlock,flags);

/*視頻解碼:視頻傳輸關鍵*/
stream->decode(urb,stream,buf);

/*提交urb*/
if((ret=usb_submit_urb(urb,GFP_ATOMIC))

host 端視頻數據解碼:

stream->decode(urb,stream,buf);
uvc_video_decode_bulk();
uvc_video_decode_start();//解析uvcheader
uvc_video_decode_data();//解析視頻數據
uvc_video_decode_end();//幀結束標記

3.2 device 端

源碼位置:driver/usb/gadget/function

ISO 開關流

staticintuvc_function_set_alt(structusb_function*f,unsignedinterface,unsignedalt)
{
.......
/*VideoControlprocess*/
if(interface==uvc->control_intf){
/*復位控制端點*/
usb_ep_disable(uvc->control_ep);
...
usb_ep_enable(uvc->control_ep);

if(uvc->state==UVC_STATE_DISCONNECTED){
/*提交uvc狀態(tài)*/
memset(&v4l2_event,0,sizof(v4l2_evetn);
v4l2_event.type=UVC_EVENT_CONNECT;
uvc_event->speed=cdev->gadget->speed;
v4l2_event_queue(&uvc->vdev,&v4l2_event);
uvc->state=UVC_STATE_CONNECTED;
}

return0;

}
/*VideoStreamprocess*/
if(interface!=uvc->streaming_intf){
return-EINVAL;
}

/*判斷端點是否為bulk 端點:*/
if(usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)){
/*使能端點*/
usb_ep_enable(uvc->video_ep);
returnalt?-EIVAL:0;
}

/*ISO開關流處理*/
switch(alt){
case0:
if(uvc->state!=UVC_STATE_STREAMING)
return0;

if(uvc->video.ep)
usb_ep_disable(uvc->video.ep);

/*提交應用:關流*/
memset(&v4l2_event,0,sizeof(v4l2_event));
v4l2_event.type=UVC_EVENT_STREAMOFF;
v4l2_event_queue(&uvc->vdev,&v4l2_event);

uvc->state=UVC_STATE_CONNECTED;
return0;

case1:
if(uvc->state!=UVC_STATE_CONNECTED)
return0;

if(!uvc->video.ep)
return-EINVAL;

INFO(cdev,"resetUVC
");
usb_ep_disable(uvc->video.ep);

ret=config_ep_by_speed(f->config->cdev->gadget,
&(uvc->func),uvc->video.ep);
if(ret)
returnret;
usb_ep_enable(uvc->video.ep);

/*開流*/
memset(&v4l2_event,0,sizeof(v4l2_event));
v4l2_event.type=UVC_EVENT_STREAMON;
v4l2_event_queue(&uvc->vdev,&v4l2_event);
returnUSB_GADGET_DELAYED_STATUS;

default:
return-EINVAL;
}

}

bulk 傳輸開關流

uvc_function_setup(structusb_function*f,conststructusb_ctrlrequest*ctrl)
{
structuvc_device*uvc=to_uvc(f);
structv4l2_eventv4l2_event;
structuvc_event*uvc_event=(void*)&v4l2_event.u.data;

/*printk(KERN_INFO"setuprequest%02x%02xvalue%04xindex%04x%04x
",
*ctrl->bRequestType,ctrl->bRequest,le16_to_cpu(ctrl->wValue),
*le16_to_cpu(ctrl->wIndex),le16_to_cpu(ctrl->wLength));
*/

if((ctrl->bRequestType&USB_TYPE_MASK)!=USB_TYPE_CLASS){
/* bulk 傳輸關流:需要修改udc 控制器,將usb 控制器clear_halt 注冊到uvc function 驅動里面*/
if(usb_endpoint_xfer_bulk(&uvc->desc.vs_ep)){
memset(&v4l2_event,0,sizeof(v4l2_event));
v4l2_event.type=UVC_EVENT_STREANOFF;
memcpy(&uvc_event->req,ctrl,sizeof(uvc_event->req));
v4l2_event_queue(&uvc->vdev,&v4l2_event);

}else{
INFO(f->config->cdev,"invalidrequesttype
");
return-EINVAL;
}

}

/*Stalltoobigrequests.*/
if(le16_to_cpu(ctrl->wLength)>UVC_MAX_REQUEST_SIZE)
return-EINVAL;

/*Tellthecompletecallbacktogenerateaneventforthenextrequest
*thatwillbeenqueuedbyUVCIOC_SEND_RESPONSE.
*/
uvc->event_setup_out=!(ctrl->bRequestType&USB_DIR_IN);
uvc->event_length=le16_to_cpu(ctrl->wLength);

/* bulk 傳輸開流:通過uvc probe 和 commit 提交分辨率和幀率控制*/
memset(&v4l2_event,0,sizeof(v4l2_event));
v4l2_event.type=UVC_EVENT_SETUP;
memcpy(&uvc_event->req,ctrl,sizeof(uvc_event->req));
v4l2_event_queue(&uvc->vdev,&v4l2_event);

return0;
}

4. 總結

15eed522-5ae6-11ee-939d-92fbcf53809c.png

整個bulk 傳輸控制流程如上圖所示。

對于linux 平臺而言,需要關心的有兩點:1)如何將底層clear_halt 請求 與uvc_function 請求關聯上,而不影響其他端點;2)如何將clear_halt 請求提交到應用層去處理。這一步不是非必須的。

對于Rtos 平臺大同小異,只要理解了整個開關流流程,處理起來自然簡單許多。

審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8447

    瀏覽量

    150720
  • usb
    usb
    +關注

    關注

    60

    文章

    7876

    瀏覽量

    263697
  • Bulk
    +關注

    關注

    0

    文章

    8

    瀏覽量

    8642
  • uvc
    uvc
    +關注

    關注

    1

    文章

    126

    瀏覽量

    14489

原文標題:UVC Bulk 傳輸實現細節(jié)

文章出處:【微信號:漫談嵌入式,微信公眾號:漫談嵌入式】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    請問Bulk傳輸是否可以被Interrupt傳輸打斷?

    我用win10電腦與FX3設備進行通信,需要用Bulk傳輸從FX3讀取大批量數據,但同時每100ms需用Interrupt EP去讀取少量數據,驅動使用的Cypress的。 想問一下Bulk
    發(fā)表于 02-28 06:13

    請問FX3可以實現SlaveFifoSync+UVC嗎?

    想讓FX3實現SlaveFifoSync+UVC,具體是: FPGA將產生的視頻數據以SlaveFifoSync方式傳輸給FX3,FX3再以UVC方式發(fā)送給上位機。 請問這樣如何
    發(fā)表于 02-28 07:18

    使用AN75779進行UVC傳輸的時候,在上位機端實時傳輸會有圖像幀丟失的原因?

    我在使用AN75779進行UVC傳輸的時候,發(fā)現在上位機端(virtualDub軟件和ampcap以及我們自己編寫的DirectShow程序)實時傳輸的時候偶爾會有圖像幀丟失。丟失的頻率在不同的電腦
    發(fā)表于 02-28 06:12

    AN75779 FX3 + UVC切換到異步模式時丟失數據的原因?

    我和我的團隊正在TLE9243QK_BASE_BOARDAN75779 源代碼上開發(fā)自定義 FX3 + UVC 應用程序 ,并在嘗試實現同步通信時遇到問題。 到目前為止,我們按照KBA231897中
    發(fā)表于 03-06 07:19

    cyfxuvcinmem_bulk示例無法在FX3 SuperSpeed Explorer套件003上運行的原因?

    我正試圖在我的 SuperSpeed explorer 套件上加載 cyfxuvcinmem_bulk 示例,但是一旦我將固件上傳到 RAM 或 I2C,設備就無法在我的筆記本電腦上枚舉出 UVC
    發(fā)表于 05-27 06:16

    請問如何在STM32F407的USB_MSC例程上實現USB_OTG_FS與PC之間的bulk模式傳輸數據

    本人利用cube生成的USB_MSC(設備模式)的工程,如何在STM32F407的USB_MSC例程上修改以實現USB_OTG_FS與PC之間的bulk模式傳輸數據,請做過的大俠指導一下~
    發(fā)表于 02-14 07:00

    基于FPGA+USB3.0的UVC Camera實現方案

    `基于FPGA+USB3.0的UVC Camera實現方案AT7_Xilinx開發(fā)板(USB3.0+LVDS)資料共享騰訊鏈接:https://share.weiyun.com/5GQyKKc1
    發(fā)表于 03-18 17:16

    PC處理速度UVC數據太低?

    大家好!在CyPress FX3上成功完成了YUV格式數據UVC批量模式的傳輸,通過打印每秒DMABUF計數,測試了數據傳輸速度,最大可達200 Mb/s。ARG:最大突發(fā)大?。?6DMABUF大小
    發(fā)表于 04-25 09:47

    如何使用cyfxuvcinmem_bulk示例?

    傳輸是否在Windows 8上工作。謝謝,亨利 以上來自于百度翻譯 以下為原文Hi,I compiled cyfxuvcinmem_bulk which is one of the two
    發(fā)表于 05-09 09:34

    USB_BULK傳輸音頻文件后不能用MCASP播放

    因為課題需要,想實現USB_bulk傳輸接受到音頻數據文件后,然后將用查詢的方式將數據播放出來,但是實際操作發(fā)現,一直卡在MCASP的發(fā)送上了,不知道該怎么解決,我的主函數如下:int main
    發(fā)表于 09-03 06:24

    【每日一知識點】在STM32F4上OTG 主機庫在 BULK 傳輸上對 NAK 的處理

    問題:某客戶使用 STM32F4 的 OTG 庫做 USB 主機控制 Wifi 網卡。使用 BULK 傳輸類型時,從數據讀取數據時,如果設備返回需要把設備返回的 NAK 狀態(tài)告知上層應用,該如何修改
    發(fā)表于 06-02 15:22

    基于STM32F105實現USB-BULK傳輸

    基于STM32F105 實現USB-BULK傳輸由于項目需要,需要USB來傳輸,之前試的HID模式是已經調通,HID基于中斷傳輸,一毫秒偵測
    發(fā)表于 08-18 06:05

    請問STM32F105如何實現USB BULK傳輸

    請問STM32F105如何實現USB BULK傳輸?
    發(fā)表于 11-23 07:08

    07 Bulk設備

    07 Bulk設備
    發(fā)表于 10-11 09:19 ?6次下載
    07 <b class='flag-5'>Bulk</b>設備

    如何使用luvcview來實現UVC雙攝像頭拍攝

    Ubuntu下使用測試UVC 攝像頭的工具有l(wèi)uvcview、mplayer等,我們就來介紹如何使用luvcview來實現UVC雙攝像頭拍攝。
    的頭像 發(fā)表于 10-30 14:35 ?9915次閱讀