UVC 等时传输中的URB_ISOCH_TRANSFER

506 阅读1分钟

原文来自:www.usbzh.com/article/det…

通过UVC规范可知,视频图像数据的读取可使用两种端点传输方式,分别为:

  • BULK 块/批量传输方式
  • ISO 等时/同步传输方式

在Windows内核中,USB数据的读取是通过URB来进行传输的,其结构体是一个大大的共用体,根据数据传输的方式对应其不同的结构体,其内容如下:

typedef _Struct_size_bytes_(UrbHeader.Length) struct _URB {
    union {
        struct _URB_HEADER
            UrbHeader;
        struct _URB_SELECT_INTERFACE
            UrbSelectInterface;
        struct _URB_SELECT_CONFIGURATION
            UrbSelectConfiguration;
        struct _URB_PIPE_REQUEST
            UrbPipeRequest;
        struct _URB_FRAME_LENGTH_CONTROL
            UrbFrameLengthControl;
        struct _URB_GET_FRAME_LENGTH
            UrbGetFrameLength;
        struct _URB_SET_FRAME_LENGTH
            UrbSetFrameLength;
        struct _URB_GET_CURRENT_FRAME_NUMBER
            UrbGetCurrentFrameNumber;
        struct _URB_CONTROL_TRANSFER
            UrbControlTransfer;

    #if (_WIN32_WINNT >= 0x0600)

        struct _URB_CONTROL_TRANSFER_EX
            UrbControlTransferEx;

    #endif

        struct _URB_BULK_OR_INTERRUPT_TRANSFER
            UrbBulkOrInterruptTransfer;
        struct _URB_ISOCH_TRANSFER
            UrbIsochronousTransfer;
        struct _URB_CONTROL_DESCRIPTOR_REQUEST
            UrbControlDescriptorRequest;
        struct _URB_CONTROL_GET_STATUS_REQUEST
            UrbControlGetStatusRequest;
        struct _URB_CONTROL_FEATURE_REQUEST
            UrbControlFeatureRequest;
        struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST
            UrbControlVendorClassRequest;
        struct _URB_CONTROL_GET_INTERFACE_REQUEST
            UrbControlGetInterfaceRequest;
        struct _URB_CONTROL_GET_CONFIGURATION_REQUEST
            UrbControlGetConfigurationRequest;

    #if (_WIN32_WINNT >= 0x0501)

        struct _URB_OS_FEATURE_DESCRIPTOR_REQUEST
            UrbOSFeatureDescriptorRequest;
    #endif

    #if (NTDDI_VERSION >= NTDDI_WIN8)

        struct _URB_OPEN_STATIC_STREAMS
            UrbOpenStaticStreams;

    #endif


    #if (NTDDI_VERSION >= NTDDI_WIN10_RS3)


        struct _URB_GET_ISOCH_PIPE_TRANSFER_PATH_DELAYS
            UrbGetIsochPipeTransferPathDelays;

    #endif

    };

} URB, *PURB;

当时行等时传输方式,URB可制转换为URB_ISOCH_TRANSFER结构体:

struct _URB_ISOCH_TRANSFER* iso = (struct _URB_ISOCH_TRANSFER*)Urb;

该结构体的定义为:

typedef struct _USBD_ISO_PACKET_DESCRIPTOR {
    ULONG Offset;
    ULONG Length;
    USBD_STATUS Status;
} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;

struct _URB_ISOCH_TRANSFER {
    struct _URB_HEADER Hdr;
    USBD_PIPE_HANDLE PipeHandle;
    ULONG TransferFlags;
    ULONG TransferBufferLength;
    PVOID TransferBuffer;
    PMDL TransferBufferMDL;
    struct _URB *UrbLink; // Reserved
    struct _URB_HCD_AREA hca; // Reserved
    ULONG StartFrame;
    ULONG NumberOfPackets  ;
    ULONG ErrorCount;
    USBD_ISO_PACKET_DESCRIPTOR IsoPacket[1];
};

这个结构体中有内个关键成员解释如下:

  • TransferBufferLength 总数据长度,一般 >= NumberOfPackets * USBD_ISO_PACKET_DESCRIPTOR::Length,读完后修正为实际的数据总长度。
  • NumberOfPackets代表着当前一个URB需要进行数据传输的IsoPacket的个数,
  • USBD_ISO_PACKET_DESCRIPTOR结构体中的Offset一般是由视频流选择子VS_COMMIT_CONTROL/VS_PROBE_CONTROL对应的结构体中的dwMaxPayloadTransferSize指定