原文转自于:http://usb.bytekits.com/uvcpacketcaptureexample/uvc-close-camera-process.html
通过UVC协议规范可以知道,UVC的数据传输支持USB四种传输中的批量传输和同步传输,所以对于UVC摄像头,当我们在摄像头正在工作时,需要停止摄像头工作,执行的操作是不同的。
在Linux的源代码中,摄像头的流关闭是由函数uvc_video_stop_streaming完成的。代码比较简单,我们直接给出原代码
linux-5.6.11\linux-5.6.11\drivers\media\usb\uvc\uvc_video.c:2080
void uvc_video_stop_streaming(struct uvc_streaming *stream)
{
uvc_video_stop_transfer(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);
}
UVC摄像头同步传输的关闭
在UVC规范中,如果采用同步数据传输,那么数据流接口的转换接口为0的接口中默认是没有端点描述符中,是用于摄像头关闭或者不工作时;而转换接口非0的接口中含有对应的同步传输端点,用于数据传输。
如本人手中的一个摄像头,是一个多转换接口的UVC摄像头,在摄像头关闭时,抓包内容如下:
CTL 01 0b 00 00 01 00 00 00 SET INTERFACE
可以看到,发送选择接口命令,接口ID=1,转换接口ID=0
视频流转换接口ID=1:
---------------- Interface Descriptor -----------------
bLength : 0x09 (9 bytes)
bDescriptorType : 0x04 (Interface Descriptor)
bInterfaceNumber : 0x01
bAlternateSetting : 0x01
bNumEndpoints : 0x01 (1 Endpoint)
bInterfaceClass : 0x0E (Video)
bInterfaceSubClass : 0x02 (Video Streaming)
bInterfaceProtocol : 0x00
iInterface : 0x06 (String Descriptor 6)
Language 0x0409 : "Video Streaming"
Data (HexDump) : 09 04 01 01 01 0E 02 00 06 .........
----------------- Endpoint Descriptor -----------------
bLength : 0x07 (7 bytes)
bDescriptorType : 0x05 (Endpoint Descriptor)
bEndpointAddress : 0x81 (Direction=IN EndpointID=1)
bmAttributes : 0x05 (TransferType=Isochronous SyncType=Asynchronous EndpointType=Data)
wMaxPacketSize : 0x03FF
Bits 15..13 : 0x00 (reserved, must be zero)
Bits 12..11 : 0x00 (0 additional transactions per microframe -> allows 1..1024 bytes per packet)
Bits 10..0 : 0x3FF (1023 bytes per packet)
bInterval : 0x01 (1 ms)
Data (HexDump) : 07 05 81 05 FF 03 01 .......
通过BUSHOUND显示的设备端点信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bVZeUdLu-1617421778250)(/res/img/gather/uvcpacketcaptureexample/1617244075973.png ‘VC摄像头同步传输端点’)]
UVC摄像头批量传输的关闭
批量传输是需要是需要停止当前的数据传输,故需要Reset。在Linux源代码中是通过usb_clear_halt函数实现的。
后续内容详见:http://usb.bytekits.com/uvcpacketcaptureexample/uvc-close-camera-process.html