UVC摄像头的关闭流程及抓包分析
2021-04-01
2243
0
通过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显示的设备端点信息:
UVC摄像头批量传输的关闭
批量传输是需要是需要停止当前的数据传输,故需要Reset。在Linux源代码中是通过usb_clear_halt函数实现的。
int usb_clear_halt(struct usb_device *dev, int pipe)
{
int result;
int endp = usb_pipeendpoint(pipe);
if (usb_pipein(pipe))
endp |= USB_DIR_IN;
/* we don't care if it wasn't halted first. in fact some devices
* (like some ibmcam model 1 units) seem to expect hosts to make
* this request for iso endpoints, which can't halt!
*/
result = usb_control_msg_send(dev, 0,
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
USB_ENDPOINT_HALT, endp, NULL, 0,
USB_CTRL_SET_TIMEOUT, GFP_NOIO);
/* don't un-halt or force to DATA0 except on success */
if (result)
return result;
/* NOTE: seems like Microsoft and Apple don't bother verifying
* the clear "took", so some devices could lock up if you check...
* such as the Hagiwara FlashGate DUAL. So we won't bother.
*
* NOTE: make sure the logic here doesn't diverge much from
* the copy in usb-storage, for as long as we need two copies.
*/
usb_reset_endpoint(dev, endp);
return 0;
}
抓包如下:
44.3 RESET
从抓包分析可知,对该端点进行复位。
通过BUSHOUND显示该设备的端点信息.
HID人机交互QQ群:564808376
UAC音频QQ群:218581009
UVC相机QQ群:331552032
BOT&UASP大容量存储QQ群:258159197
STC-USB单片机QQ群:315457461
USB技术交流QQ群2:580684376
USB技术交流QQ群:952873936