usbx icon indicating copy to clipboard operation
usbx copied to clipboard

I coudn't able to find uvc device class support sample application in usbx

Open MaheshAvula-Alifsemi opened this issue 1 year ago • 39 comments

Describe the bug Actually I am trying to give uvc device class support, I am looking for any sample application or any document to understand the flow of UVC.

Can anyone help on this.

Please also mention any information which could help others to understand the problem you're facing:

  • I am using target board as cortex m55
  • release version 6.2.0

MaheshAvula-Alifsemi avatar Mar 02 '23 06:03 MaheshAvula-Alifsemi

To use UVC on device side, following things need to be done:

  1. Prepare descriptors (passed to stack as "framework"), .e.g., a simulated video camera:
/* Define device payloadwork.  */

#define W(d)        UX_DW0(d), UX_DW1(d)
#define DW(d)       UX_DW0(d), UX_DW1(d), UX_DW2(d), UX_DW3(d)
#define GUID_YUY2   0x59,0x55,0x59,0x32, 0x00,0x00, 0x10,0x00, 0x80,0x00, 0x00,0xAA,0x00,0x38,0x9B,0x71 /* 32595559-0000-0010-8000-00AA00389B71 */

#define _DEVICE_DESCRIPTOR()                                                                        \
/* --------------------------------------- Device Descriptor */                                     \
/* 0  bLength, bDescriptorType                               */ 18,   0x01,                         \
/* 2  bcdUSB                                                 */ W(0x200),                           \
/* 4  bDeviceClass, bDeviceSubClass, bDeviceProtocol         */ 0xEF, 0x02, 0x01,                   \
/* 7  bMaxPacketSize0                                        */ 64,                                 \
/* 8  idVendor, idProduct                                    */ 0x84, 0x84, 0x01, 0x00,             \
/* 12 bcdDevice                                              */ UX_DW0(0x100),UX_DW1(0x100),        \
/* 14 iManufacturer, iProduct, iSerialNumber                 */ 0,    0,    0,                      \
/* 17 bNumConfigurations                                     */ 1,

#define _DEVICE_QUALIFIER_DESCRIPTOR()                                                              \
/* ----------------------------- Device Qualifier Descriptor */                                     \
/* 0 bLength, bDescriptorType                                */ 10,                 0x06,           \
/* 2 bcdUSB                                                  */ W(0x200),                           \
/* 4 bDeviceClass, bDeviceSubClass, bDeviceProtocol          */ 0xEF,               0x02, 0x01,     \
/* 7 bMaxPacketSize0                                         */ 8,                                  \
/* 8 bNumConfigurations                                      */ 1,                                  \
/* 9 bReserved                                               */ 0,

#define _CONFIGURE_DESCRIPTOR(total_len,n_ifc,cfg_v)                                                \
/* -------------------------------- Configuration Descriptor */                                     \
/* 0 bLength, bDescriptorType                                */ 9,    0x02,                         \
/* 2 wTotalLength                                            */ W(total_len),                       \
/* 4 bNumInterfaces, bConfigurationValue                     */ (n_ifc), (cfg_v),                   \
/* 6 iConfiguration                                          */ 0,                                  \
/* 7 bmAttributes, bMaxPower                                 */ 0x80, 50,

#define _IAD_DESCRIPTOR(ifc_0,ifc_cnt,cls,sub,protocol)                                             \
/* ------------------------ Interface Association Descriptor */                                     \
/* 0 bLength, bDescriptorType                                */ 8,    0x0B,                         \
/* 2 bFirstInterface, bInterfaceCount                        */ (ifc_0), (ifc_cnt),                 \
/* 4 bFunctionClass, bFunctionSubClass, bFunctionProtocol    */ (cls), (sub), (protocol),           \
/* 7 iFunction                                               */ 0,

#define _INTERFACE_DESCRIPTOR(ifc,alt,n_ep,cls,sub,protocol)                                        \
/* ------------------------------------ Interface Descriptor */                                     \
/* 0 bLength, bDescriptorType                                */ 9,    0x04,                         \
/* 2 bInterfaceNumber, bAlternateSetting                     */ (ifc), (alt),                       \
/* 4 bNumEndpoints                                           */ (n_ep),                             \
/* 5 bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol */ (cls), (sub), (protocol),           \
/* 8 iInterface                                              */ 0,

#define _ENDPOINT_DESCRIPTOR(addr,attr,pkt_siz,interval)                                            \
/* ------------------------------------- Endpoint Descriptor */                                     \
/* 0  bLength, bDescriptorType                                */ 7,               0x05,             \
/* 2  bEndpointAddress, bmAttributes                          */ (addr),          (attr),           \
/* 4  wMaxPacketSize, bInterval                               */ W(pkt_siz),      (interval),

#define _VC_DESCRIPTORS_LEN (13+17+9+13)
#define _VC_DESCRIPTORS()                                                                           \
    /*--------------------------- Class VC Interface Descriptor (VC_HEADER).  */                    \
    13, 0x24, 0x01, W(0x110),                                                                       \
    W(_VC_DESCRIPTORS_LEN), /* wTotalLength.  */                                                    \
    DW(UX_DEMO_CLOCK_FREQUENCY),  /* dwClockFrequency.  */                                          \
    1, /* bInCollection.  */                                                                        \
    1, /* BaInterfaceNr(1).  */                                                                     \
    /*--------------------------- Input Terminal (VC_INPUT_TERMINAL, Camera)  */                    \
    17, 0x24, 0x02,                                                                                 \
    0x01, /* bTerminalID, ITT_CAMERA  */                                                            \
    W(0x201), /* wTerminalType  */                                                                  \
    0x00, 0x00, W(0), W(0), W(0),                                                                   \
    0x02, W(0), /* bControlSize, bmControls  */                                                     \
    /*---------------------------- Output Terminal (VC_OUTPUT_TERMINAL, USB)  */                    \
    9, 0x24, 0x03,                                                                                  \
    0x02, /* bTerminalID  */                                                                        \
    W(0x0101), /* wTerminalType, TT_STREAMING  */                                                   \
    0x00, 0x05/* bSourceID  */, 0x00,                                                               \
    /*--------------------------------- Processing Unit (VC_PROCESSING_UNIT)  */                    \
    13, 0x24, 0x05,                                                                                 \
    0x05, /* bUnitID  */                                                                            \
    0x01, /* bSourceID  */                                                                          \
    W(0), /* wMaxMultiplier  */                                                                     \
    3, 0x00, 0x00, 0x00, /* bControlSize, bmControls  */                                            \
    0, /* iProcessing  */                                                                           \
    0x00, /* bmVideoStandards  */                                                                   \


#define _VS_FORMAT_DESCRIPTORS_UNCOMPRESSED_LEN (27+30)
#define _VS_FORMAT_DESCRIPTORS_UNCOMPRESSED()                                                       \
    /*------------------------------- VS Format Descriptor (VS_FORMAT_UNCOMPRESSED)  */             \
    27, 0x24, 0x04,                                                                                 \
    0x01, /* bFormatIndex  */                                                                       \
    0x01, /* bNumFrameDescriptors  */                                                               \
    GUID_YUY2, /* YUY2 : YUV 4:2:2  */                                                              \
    16, /* bBitsPerPixel  */                                                                        \
    0x01, /* bDefaultFrameIndex  */                                                                 \
    0x00, 0x00,                                                                                     \
    0x00, /* bmInterlaceFlags  */                                                                   \
    0x00, /* bCopyProtect  */                                                                       \
    /*--------------------------------- VS Frame Descriptor (VS_FRAME_UNCOMPRESSED)  */             \
    30, 0x24, 0x05,                                                                                 \
    0x01, /* bFrameIndex  */                                                                        \
    0x00, /* bmCapabilities  */                                                                     \
    W(176), W(144), /* wWidth, wHeight  */                                                          \
    DW(912384), DW(912384), /* dwMinBitRate, dwMaxBitRate  */                                       \
    DW(UX_DEMO_FRAME_DATA_SIZE), /* dwMaxVideoFrameBufSize  */                                      \
    DW(UX_DEMO_FRAME_INTERVAL), /* dwDefaultFrameInterval  */                                       \
    0x01, /* bFrameIntervalType  */                                                                 \
    DW(UX_DEMO_FRAME_INTERVAL), /* dwMinFrameInterval(1) */

#define _VS_IN_DESCRIPTORS_LEN (14+_VS_FORMAT_DESCRIPTORS_UNCOMPRESSED_LEN)
#define _VS_IN_DESCRIPTORS()                                                                        \
    /*------------------------- Class VS Header Descriptor (VS_INPUT_HEADER)  */                    \
    14, 0x24, 0x01,                                                                                 \
    0X01, /* bNumFormats  */                                                                        \
    W(_VS_IN_DESCRIPTORS_LEN), /* wTotalLength  */                                                  \
    0x81, /* bEndpointAddress  */                                                                   \
    0x00,                                                                                           \
    0x02, /* bTerminalLink  */                                                                      \
    0x00, /* bStillCaptureMethod  */                                                                \
    0x00, 0x00, /* bTriggerSupport, bTriggerUsage  */                                               \
    0x01, 0x00, /* bControlSize, bmaControls  */                                                    \
    _VS_FORMAT_DESCRIPTORS_UNCOMPRESSED()

#define _VS_OUT_DESCRIPTORS_LEN (11+_VS_FORMAT_DESCRIPTORS_UNCOMPRESSED_LEN)
#define _VS_OUT_DESCRIPTORS()                                                                       \
    /*------------------------- Class VS Header Descriptor (VS_OUTPUT_HEADER)  */                   \
    11, 0x24, 0x02,                                                                                 \
    0x01, /* bNumFormats  */                                                                        \
    W(_VS_OUT_DESCRIPTORS_LEN), /* wTotalLength  */                                                 \
    0x02, /* bEndpointAddress  */                                                                   \
    0x00,                                                                                           \
    0x03, /* bTerminalLink  */                                                                      \
    0x01, 0x00, /* bControlSize, bmaControls  */                                                    \
    _VS_FORMAT_DESCRIPTORS_UNCOMPRESSED()

#define _CONFIGURE_DESCRIPTORS_LEN (9+ 8+ 9+_VC_DESCRIPTORS_LEN+ 9+_VS_IN_DESCRIPTORS_LEN+9+7)
#if UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH < _CONFIGURE_DESCRIPTORS_LEN
#error Please increase control request buffer size
#endif
#if UX_SLAVE_REQUEST_DATA_MAX_LENGTH < UX_DEMO_MAX_PAYLOAD_SIZE
#error Please increase endpoint data buffer size
#endif

unsigned char device_payloadwork_full_speed[] = {
    _DEVICE_DESCRIPTOR()
     _CONFIGURE_DESCRIPTOR(_CONFIGURE_DESCRIPTORS_LEN,2,1)
      _IAD_DESCRIPTOR(0,2,0x0E,0x03,0x00)

       _INTERFACE_DESCRIPTOR(0,0,0,0x0E,0x01,0x00)
        _VC_DESCRIPTORS()

       _INTERFACE_DESCRIPTOR(1,0,0,0x0E,0x02,0x00)
        _VS_IN_DESCRIPTORS()
        _INTERFACE_DESCRIPTOR(1,1,1,0x0E,0x02,0x00)
        _ENDPOINT_DESCRIPTOR(0x81,0x05,UX_DEMO_ENDPOINT_SIZE,UX_DEMO_ENDPOINT_INTERVAL_FS)

};
#define             DEVICE_FRAMEWORK_LENGTH_FULL_SPEED      sizeof(device_payloadwork_full_speed)

unsigned char device_payloadwork_high_speed[] = {
    _DEVICE_DESCRIPTOR()
     _DEVICE_QUALIFIER_DESCRIPTOR()
     _CONFIGURE_DESCRIPTOR(_CONFIGURE_DESCRIPTORS_LEN,2,1)
      _IAD_DESCRIPTOR(0,2,0x0E,0x03,0x00)

       _INTERFACE_DESCRIPTOR(0,0,0,0x0E,0x01,0x00)
        _VC_DESCRIPTORS()

       _INTERFACE_DESCRIPTOR(1,0,0,0x0E,0x02,0x00)
        _VS_IN_DESCRIPTORS()
        _INTERFACE_DESCRIPTOR(1,1,1,0x0E,0x02,0x00)
        _ENDPOINT_DESCRIPTOR(0x81,0x05,UX_DEMO_ENDPOINT_SIZE,UX_DEMO_ENDPOINT_INTERVAL_HS)
};
#define             DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED      sizeof(device_payloadwork_high_speed)

  1. Setup video stream and video, e.g., for upper simulated camera:
    /* Set the parameters for Video streams.  */
    video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_change     = demo_video_write_change;
    video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_payload_done = demo_video_write_done;
    video_stream_parameter[0].ux_device_class_video_stream_parameter_max_payload_buffer_nb   = UX_DEMO_PAYLOAD_BUFFER_NB;
    video_stream_parameter[0].ux_device_class_video_stream_parameter_max_payload_buffer_size = UX_DEMO_MAX_PAYLOAD_SIZE;
    video_stream_parameter[0].ux_device_class_video_stream_parameter_thread_entry = ux_device_class_video_write_thread_entry;

    /* Set the parameters for Video device.  */
    video_parameter.ux_device_class_video_parameter_streams_nb  = 1;
    video_parameter.ux_device_class_video_parameter_streams     = video_stream_parameter;
    video_parameter.ux_device_class_video_parameter_callbacks.ux_slave_class_video_instance_activate      = demo_video_instance_activate;
    video_parameter.ux_device_class_video_parameter_callbacks.ux_slave_class_video_instance_deactivate    = demo_video_instance_deactivate;

    video_parameter.ux_device_class_video_parameter_callbacks.ux_device_class_video_request                         = demo_video_vc_request_process;
    video_stream_parameter[0].ux_device_class_video_stream_parameter_callbacks.ux_device_class_video_stream_request = demo_video_vs_request_process;

    /* Initialize the device Video class. This class owns interfaces starting with 0. */
     status =  ux_device_stack_class_register(_ux_system_device_class_video_name, ux_device_class_video_entry,
                                              1, 0, &video_parameter);

callback.ux_device_class_video_stream_change: callback invoked if host select interface alternate setting (0 to close video stream, other value to open video stream in specific data rate) callbacks.ux_device_class_video_stream_payload_done: callback invoked when a video frame is sent to host (example here is video camera) _max_payload_buffer_nb and _max_payload_buffer_size: passed to stack to create a ring buffer to caching payloads, the size is usually the max possible isochronous endpoint size. _thread_entry: ux_device_class_video_write_thread_entry for camera (device sending data to host).

At least stream request should be assigned, since application should handle some request (following the request is simply accepted, but in real application video parameters should be applied and returned in specific format):

UINT    demo_video_vs_request_process(UX_DEVICE_CLASS_VIDEO_STREAM *stream, UX_SLAVE_TRANSFER *transfer)
{

UINT                                    status = UX_ERROR;
UCHAR                                   bRequest;
USHORT                                  wValue_CS; /* In high byte.  */
USHORT                                  wLength;
UCHAR                                   *data;

    /* Decode setup packet.  */
    bRequest = transfer -> ux_slave_transfer_request_setup[UX_SETUP_REQUEST];
    wValue_CS = transfer -> ux_slave_transfer_request_setup[UX_SETUP_VALUE + 1];
    wLength = ux_utility_short_get(transfer -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
    data = transfer -> ux_slave_transfer_request_data_pointer;

    /* Check CS.  */
    switch(wValue_CS)
    {
    case UX_DEVICE_CLASS_VIDEO_VS_PROBE_CONTROL:

        switch(bRequest)
        {
        case UX_DEVICE_CLASS_VIDEO_SET_CUR:

            /* Simply accept without change setting.  */
            status = UX_SUCCESS;
            break;

        case UX_DEVICE_CLASS_VIDEO_GET_CUR:
        case UX_DEVICE_CLASS_VIDEO_GET_MIN:
        case UX_DEVICE_CLASS_VIDEO_GET_MAX:

            /* Simply send our data back (first 26 bytes).  */

            /* Check request length.  */
            if (wLength < 26)
                break;

            /* Copy data for transfer.  */
            ux_utility_memory_copy(data, video_probe_commit_buffer, 26);

            /* Transfer request.  */
            status = ux_device_stack_transfer_request(transfer, 26, wLength);
            break;

        default:
            break;
        }

        break;

    case UX_DEVICE_CLASS_VIDEO_VS_COMMIT_CONTROL:

        /* Simply accept request.  */
        status = UX_SUCCESS;
        break;

    /* CS not supported now.  */
    default:
        break;
    }

    return(status);
}
  1. After host activate the stream (change callback with none-zero alternate setting), in application payload buffer can be filled to streaming data, ux_device_class_video_write_payload_get is used to get data buffer to fill things and ux_device_class_video_write_payload_commit is used to commit the filled buffer. Background transfer is started once ux_device_class_video_transmission_start is called. Once a payload is sent there is a callback to let application to fill more buffer .
static VOID demo_video_write_a_payload(UX_DEVICE_CLASS_VIDEO_STREAM *stream)
{
UCHAR                                   *buffer;
ULONG                                   buffer_length, length;
UX_DEVICE_CLASS_VIDEO_PAYLOAD_HEADER    *header;
UCHAR                                   *data;
UCHAR                                   *frame_data;

    /* If disabled, no write.  */
    if (video_payload_data_length == 0)
        return;

    /* Get payload buffer.  */
    ux_device_class_video_write_payload_get(stream, &buffer, &buffer_length);
    header = (UX_DEVICE_CLASS_VIDEO_PAYLOAD_HEADER *)buffer;
    data = buffer + UX_DEMO_PAYLOAD_HEADER_SIZE;

    /* Get frame data buffer.  */
    frame_data = video_frame_buffer + video_frame_write_pos;

    /* Calculate data length.  */
    length = video_frame_buffer_size - video_frame_write_pos;
    if (length > video_payload_data_length)
        length = video_payload_data_length;

    /* Fill data.  */
    ux_utility_memory_copy(data, frame_data, length);    

    /* Fill payload header (no PTS nor SCR, total 10 bytes).  */
    header -> bHeaderLength = UX_DEMO_PAYLOAD_HEADER_SIZE;
    header -> bmHeaderInfo.value = video_frame_count & 0x1; /* FID @ B0  */
    header -> bmHeaderInfo.bm.bEOH = 1;

    /* Move write pos.  */
    video_frame_write_pos += length;
    if (video_frame_write_pos >= video_frame_buffer_size)
    {
        /* EOF.  */
        header -> bmHeaderInfo.bm.bEOF = 1;
        video_frame_write_pos = 0;

        /* A frame sent.  */
        video_frame_count ++;
    }

    /* Commit payload buffer.  */
    ux_device_class_video_write_payload_commit(stream, length + UX_DEMO_PAYLOAD_HEADER_SIZE);
}
VOID    demo_video_write_change(UX_DEVICE_CLASS_VIDEO_STREAM *stream, ULONG alternate_setting)
{
INT             i;

    /* Stop video payload loop back if stream closed.  */
    if (alternate_setting == 0)
    {
        video_payload_data_length = 0;
        return;
    }

    /* Payload data length: exclude header.  */
    video_payload_data_length = ux_device_class_video_max_payload_length(stream);
    video_payload_data_length -= UX_DEMO_PAYLOAD_HEADER_SIZE;

    /* Frame not started.  */
    video_frame_write_pos = 0;

    /* Write buffers until achieve threadshold.  */
    for (i = 0; i < UX_DEMO_TRANSMIT_START_THRESHOLD; i ++)
        demo_video_write_a_payload(stream);
    ux_device_class_video_transmission_start(stream);
}
VOID    demo_video_write_done(UX_DEVICE_CLASS_VIDEO_STREAM *stream, ULONG length)
{

    /* Invoked when a payload sent to host, currently no use for loop back.  */
    (void)stream;
    (void)length;
    if (length)
    {
        /* A payload sent.  */
        video_payload_count ++;

        /* Prepare next payload.  */
        demo_video_write_a_payload(stream);
    }
}

xiaocq2001 avatar Mar 03 '23 03:03 xiaocq2001

Hi @xiaocq2001 , Thank you so much for detailed information.

MaheshAvula-Alifsemi avatar Mar 03 '23 05:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

I have one doubt that, as you explained _max_payload_buffer_nb and _max_payload_buffer_size both the variables size would be same as Isochrnous endpoint size..? if I give both sizes as Isocronous endpoint size, class registration was failing because it requires almost 1MB memory, i have less memory on my device. memory_size = stream -> ux_device_class_video_stream_payload_buffer_size * stream_parameter -> ux_device_class_video_stream_parameter_max_payload_buffer_nb; Could you please confirm that.

Thanks Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 03 '23 08:03 MaheshAvula-Alifsemi

_buffer_size is max endpoint size, _buffer_nb is number of payloads buffered.

xiaocq2001 avatar Mar 06 '23 01:03 xiaocq2001

Thank you so much @xiaocq2001

MaheshAvula-Alifsemi avatar Mar 06 '23 05:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

Note: 1

Below are descriptors for video class driver which i have prepared, with these descriptors, Isochrnous endpoint is not creating because of this endpoint is associated with video stream interface with alternate setting =1, I have gone through code and found that my device not getting UX_SET_INTERFACE request from host machine(Ubuntu 18.04)

Could you please help on this issue, if i am doing anything wrong here.

UCHAR device_framework_high_speed[] = {

/*
Device descriptor 18 bytes
0x00 bDeviceClass: base class, the class code will be defining in interface descriptor
*/
0x12, 0x01, 0x00, 0x00,
0xEF, 0x02, 0x01, 0x40,
0x25, 0x05, 0xa7, 0xa4,
0x00, 0x01, 0x01, 0x02,
0x03, 0x01,

/* Configuration  descriptor 9 bytes  */
0x09, 0x02, 0xb5, 0x00, 0x02, 0x01, 0x00, 0xC0, 0x01,

/* Interface association descriptor  */
0x08, 0x0b, 0x00,
0x02, 0x0E, 0x03, 0x00, 0x00,

/* interface_descriptor UVC_control */
0x09, 0x04, 0x00, 0x00, 0x01, 0x0E, 0x01, 0x00, 0x00,

/* Class-specific VC Interface Header Descriptor */
 0x0d,0x24,0x01,0x10,0x01,0x34,0x00,0x00,0x00,0x00,0x00,0x01, 0x01,

  /*  Input Terminal (VC_INPUT_TERMINAL, Camera)  */
 0x11,0x24,0x02,0x01,0x01,0x02,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,

 /*  Output Terminal (VC_OUTPUT_TERMINAL, USB)  */
 0x09, 0x24, 0x03, 0x02,0x01,0x01,0x00,0x05,0x00,

  /* Processing Unit (VC_PROCESSING_UNIT)  */
 0x0d, 0x24, 0x05,0x05,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,

/* interrupt endpoint_descriptor for uvc_control 7 bytes */
0x07,0x05,0x83,0x03,0x08,0x00,0x08,

/* Interface Descriptor for UVC streaming where altsetting = 0 */
0x09, 0x04, 0x01, 0x00, 0x00, 0x0e, 0x02, 0x00, 0x00,

/* Class Video streaming input Header Descriptor (VS_INPUT_HEADER)  */
0x0e,0x24,0x01,0x01,0x47,00,0x81,0x00,0x02,0x00,0x00,0x00,0x01,0x00,

/* VS Format Descriptor (VS_FORMAT_UNCOMPRESSED)  */
0x1b,0x24,0x04,0x01,0x01,0x59,0x55,0x59,0x32, 0x00,0x00, 0x10,0x00, 0x80,0x00, 0x00,0xAA,0x00,0x38,0x9B,0x71,0x10,0x01,0x00,0x00,0x00,0x00,

 /* VS Frame Descriptor (VS_FRAME_UNCOMPRESSED)  */
0x1e,0x24, 0x05,0x01, 0x00,0x00,0x1e,0x00,0x1e,0x00,0xec,0x0d,0x00,0x00,0xec,0x0d,0x00,0x00,0x8c,0x0a,0x00,0x00,0x64,0x00,0x00,0x01,0x00,0x64,0x00,0x00,

 /* Interface Descriptor for UVC streaming where altsetting = 1 */
0x09, 0x04, 0x01, 0x01, 0x01, 0x0e, 0x02, 0x00, 0x00,

/* Isochronous IN endpoint descriptor for UVC streaming  */
0x07, 0x05, 0x85, 0x05, 0x00, 0x04, 0x01,

}

Note: 2

When I run my application I have collected dmesg logs at host side(ubuntu18.04) and attaching here. node has not created for video class driver in /dev/ directory.

[18159350.110416] usb 1-4.4.4.2: new high-speed USB device number 78 using xhci_hcd [18159350.210765] usb 1-4.4.4.2: config 1 interface 1 altsetting 1 endpoint 0x85 has an invalid bInterval 0, changing to 7 [18159350.211131] usb 1-4.4.4.2: New USB device found, idVendor=0525, idProduct=a4a7 [18159350.211132] usb 1-4.4.4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [18159350.211133] usb 1-4.4.4.2: Product: Devkit [18159350.211134] usb 1-4.4.4.2: Manufacturer: AlifSemiconductor [18159350.211152] usb 1-4.4.4.2: SerialNumber: 1200 [18159350.274379] uvcvideo: Found UVC 1.10 device Devkit (0525:a4a7) [18159360.538136] uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround. [18159365.657965] uvcvideo: Failed to query (129) UVC probe control : -110 (exp. 34). [18159365.657966] uvcvideo: Failed to initialize the device (-5).

Regards, Mahesh

MaheshAvula-Alifsemi avatar Mar 07 '23 12:03 MaheshAvula-Alifsemi

[18159360.538136] uvcvideo: UVC non compliance - GET_DEF(PROBE) not supported. Enabling workaround. [18159365.657965] uvcvideo: Failed to query (129) UVC probe control : -110 (exp. 34). [18159365.657966] uvcvideo: Failed to initialize the device (-5).

It seems the UVC requests are not handled correctly. From the log, GET_DEF(PROBE) is requested but not answered correctly. Please check the VS request callback (demo_video_vs_request_process in previous example), maybe you can try to handle GET_DEF, like following:

    switch(wValue_CS)
    {
    case UX_DEVICE_CLASS_VIDEO_VS_PROBE_CONTROL:

        switch(bRequest)
        {
        case UX_DEVICE_CLASS_VIDEO_SET_CUR:

            /* Simply accept without change setting.  */
            status = UX_SUCCESS;
            break;

        case UX_DEVICE_CLASS_VIDEO_GET_DEF: // <- when GET_DEF requsted
        case UX_DEVICE_CLASS_VIDEO_GET_CUR:
        case UX_DEVICE_CLASS_VIDEO_GET_MIN:
        case UX_DEVICE_CLASS_VIDEO_GET_MAX:

            /* Simply send our data back (first 26 bytes).  */

xiaocq2001 avatar Mar 08 '23 02:03 xiaocq2001

Hi @xiaocq2001 , Thank you so much for your inputs,

Actually VS request callback is not getting invoking because VS request callback get invoke only when UX_SET_INTERFACE request comes from the host machine, but here my device not getting UX_SET_INTERFACE request.

could you please explain that when device suppose to get UX_SET_INTERFACE from host.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 08 '23 05:03 MaheshAvula-Alifsemi

Usually UX_SET_INTERFACE is received when there is host application using the video camera, e.g., open a camera application that can preview the video input.

xiaocq2001 avatar Mar 08 '23 06:03 xiaocq2001

@xiaocq2001 , Thank you for the quick replay.

Is host application for receive video stream data from device..?,

MaheshAvula-Alifsemi avatar Mar 08 '23 06:03 MaheshAvula-Alifsemi

Yes. When host application starts receiving video stream data, the alternate setting is selected to indicate consuming USB bus bandwidth, then the ISO transfer starts to transfer video stream. When host application stops receiving video stream the interface alternate setting is back to 0 to reduce USB bus bandwidth consumed.

xiaocq2001 avatar Mar 08 '23 06:03 xiaocq2001

@xiaocq2001 , got it and thank you so much,

But still I have some doubt that as per the usbx stack When UX_SET_INTERFACE request comes from host then only Isochronous endpoint will be created and VS request callback get invoked , demo_video_vs_request_process will set the probe control and commit control right..?

Once this process is completed then device will start send video streaming data to the host right..?

could you please correct above points.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 08 '23 06:03 MaheshAvula-Alifsemi

Usually host set alternate setting to 0 and use VS request to probe control and commit control. Then host set interface to expected alternate setting and streaming data.

xiaocq2001 avatar Mar 09 '23 00:03 xiaocq2001

Hi @xiaocq2001 ,

Got it and thank you so much.

MaheshAvula-Alifsemi avatar Mar 10 '23 04:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

host setting alternate setting to 0 and VS request callback getting invoking to probe control and commit control,

I can see these two requests UX_DEVICE_CLASS_VIDEO_GET_DEF and UX_DEVICE_CLASS_VIDEO_GET_CUR, my device is receiving from host.

UINT demo_video_vs_request_process(UX_DEVICE_CLASS_VIDEO_STREAM *stream, UX_SLAVE_TRANSFER *transfer) {

UINT status = UX_ERROR; UCHAR bRequest; USHORT wValue_CS; /* In high byte. */ USHORT wLength; UCHAR *data;

/* Decode setup packet.  */
bRequest = transfer -> ux_slave_transfer_request_setup[UX_SETUP_REQUEST];
wValue_CS = transfer -> ux_slave_transfer_request_setup[UX_SETUP_VALUE + 1];
wLength = ux_utility_short_get(transfer -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
data = transfer -> ux_slave_transfer_request_data_pointer;

/* Check CS.  */
switch(wValue_CS)
{
case UX_DEVICE_CLASS_VIDEO_VS_PROBE_CONTROL:

    switch(bRequest)
    {
    case UX_DEVICE_CLASS_VIDEO_SET_CUR:

        /* Simply accept without change setting.  */
        status = UX_SUCCESS;
        break;

    case UX_DEVICE_CLASS_VIDEO_GET_CUR:
    case UX_DEVICE_CLASS_VIDEO_GET_MIN:
    case UX_DEVICE_CLASS_VIDEO_GET_MAX:

        /* Simply send our data back (first 26 bytes).  */

        /* Check request length.  */
        if (wLength < 26)
            break;

        /* Copy data for transfer.  */
        ux_utility_memory_copy(**data**, video_probe_commit_buffer, 26);
      **here, what is the  video_probe_commit_buffer ..? also we are not passing data pointer to any function below, could you please explain this**

        /* Transfer request.  */
        status = ux_device_stack_transfer_request(transfer, 26, wLength);
        break;

    default:
        break;
    }

    break;

case UX_DEVICE_CLASS_VIDEO_VS_COMMIT_CONTROL:

    /* Simply accept request.  */
    status = UX_SUCCESS;
    break;

/* CS not supported now.  */
default:
    break;
}

return(status);

}

could you please help on this

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 10 '23 05:03 MaheshAvula-Alifsemi

This is my testing data for you to reference:

/* APP specific probe/commit settings.  */
static UCHAR                            video_probe_commit_buffer[48] = {
    W(0x0000), /* bmHint  */
    1, /* bFormatIndex  */
    1, /* bFrameIndex  */
    DW(UX_DEMO_FRAME_INTERVAL), /* dwFrameInterval  */
    W(0), /* wKeyFrameRate  */
    W(0), /* wPFrameRate  */
    W(0), /* wCompQuality  */
    W(0), /* wCompWindowSize  */
    W(0), /* wDelay  */
    DW(UX_DEMO_FRAME_DATA_SIZE), /* dwMaxVideoFrameSize  */
    DW(UX_DEMO_MAX_PAYLOAD_SIZE), /* dwMaxPayloadTransferSize  */
    DW(UX_DEMO_CLOCK_FREQUENCY), /* dwClockFrequency  */
    0x03, /* bmFramingInfo  */
    1, /* bPreferedVersion  */
    1, /* bMinVersion  */
    1, /* bMaxVersion  */
    0, /* bUsage  */
    0, /* bBitDepthLuma  */
    0x00, /* bmSettings  */
    0, /* bMaxNumberOfRefFramesPlus1  */
    W(0x0000), /* bmRateControlModes  */
    W(0), W(0), W(0), W(0) /* bmLayoutPerStream  */
};

For details about the structure and fields, please refer to USB Video spec.

xiaocq2001 avatar Mar 13 '23 01:03 xiaocq2001

@xiaocq2001 , Thank you so much, We need to send this structure info to the host when probe and commit request comes right..? could you please share usbx video class driver sample application, so that it will be easy to understand,

MaheshAvula-Alifsemi avatar Mar 13 '23 02:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 , My device is enumerated at host and created node (/dev/video0)for it, I really thank you for your support.

One doubt that, from where ux_device_class_video_write_thread_entry get invoke, and could you please share any azure usbx documents for video stream data tranfer flow.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 15 '23 07:03 MaheshAvula-Alifsemi

ux_device_class_video_write_thread_entry is passed to stack to start a thread to send data in FIFO to host, the FIFO is created from parameters passed in register function. When you need to add data to FIFO, use ux_device_class_video_write_payload_get to get buffer to fill and use ux_device_class_video_write_payload_commit to commit to transfer.

BTW, which board are you working on for now?

xiaocq2001 avatar Mar 17 '23 04:03 xiaocq2001

Hi @xiaocq2001, Thanks for your support, I am using ASIC Board(with arm coretx m55 processor). I was bit struggling to write video class application , earlier I have given support for CDC-ACM class support and that was working fine.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 17 '23 05:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

Is there any open source host application for UVC driver to validate, or could you please suggest how the host application would be..?

Regards Mahesh

MaheshAvula-Alifsemi avatar Mar 20 '23 06:03 MaheshAvula-Alifsemi

Here is an example (on ST NUCLEO-H723ZG) that you can reference: https://github.com/STMicroelectronics/x-cube-azrtos-h7/tree/main/Projects/NUCLEO-H723ZG/Applications/USBX/Ux_Device_Video

xiaocq2001 avatar Mar 23 '23 02:03 xiaocq2001

Hi @xiaocq2001 ,

Thank you so much for all your inputs

MaheshAvula-Alifsemi avatar Mar 23 '23 05:03 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

I am using host application as VLC media player to stream the data from the device, but device not receiving SET_INTERFACE request with the alternate setting is selected to 1.

I have observed one thing at host side while running VLC media player , i have collected dmesg logs that i am posting here.

[20125207.047025] usb 1-4.4.4.2: new high-speed USB device number 65 using xhci_hcd [20125207.147717] usb 1-4.4.4.2: New USB device found, idVendor=0525, idProduct=a4a7 [20125207.147719] usb 1-4.4.4.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [20125207.147720] usb 1-4.4.4.2: Product: Devkit [20125207.147721] usb 1-4.4.4.2: Manufacturer: AlifSemiconductor [20125207.147722] usb 1-4.4.4.2: SerialNumber: 1200 [20125207.272416] uvcvideo: Found UVC 1.10 device Devkit (0525:a4a7) [20125207.644515] input: Devkit as /devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.4/1-4.4.4/1-4.4.4.2/1-4.4.4.2:1.0/input/input36 [20125207.650508] kauditd_printk_skb: 8 callbacks suppressed [20125207.650511] audit: type=1400 audit(1680155724.219:25407): apparmor="DENIED" operation="open" profile="snap.notepad-plus-plus.notepad-plus-plus" name="/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.4/1-4.4.4/1-4.4.4.2/busnum" pid=18819 comm="winedevice.exe" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0 [20125207.721901] audit: type=1400 audit(1680155724.291:25408): apparmor="DENIED" operation="open" profile="snap.notepad-plus-plus.notepad-plus-plus" name="/sys/devices/pci0000:00/0000:00:14.0/usb1/1-4/1-4.4/1-4.4.4/1-4.4.4.2/busnum" pid=18819 comm="winedevice.exe" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0 [20125330.019469] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125335.139257] uvcvideo: Failed to set UVC commit control : -110 (exp. 34). [20125340.259294] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.379047] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.782295] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785626] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785684] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). root@alif:/home/mahesh#

Could you please help on this.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Mar 30 '23 06:03 MaheshAvula-Alifsemi

[20125330.019469] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125335.139257] uvcvideo: Failed to set UVC commit control : -110 (exp. 34). [20125340.259294] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.379047] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.782295] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785626] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785684] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). I usually test video device under windows. But from upper log, it seems host send probe requests to device but fail. Maybe you can check if the VS control request callback in application is called and correct answer is reported to host.

xiaocq2001 avatar Mar 30 '23 09:03 xiaocq2001

Hi @xiaocq2001 , Thank you for your inputs

[20125330.019469] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125335.139257] uvcvideo: Failed to set UVC commit control : -110 (exp. 34). [20125340.259294] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.379047] uvcvideo: Failed to set UVC probe control : -110 (exp. 34). [20125345.782295] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785626] uvcvideo: Failed to set UVC probe control : -71 (exp. 34). [20125345.785684] uvcvideo: Failed to set UVC probe control : -71 (exp. 34).

These errors I have resolved, now i could see video probe control requests and commit control requests are comming also device also responding back to host.

Host application as VLC media player sending UX_SET_INTERFACE request after(video probe control requests and commit control) with the alternate setting is selected to 0, but host app suppose to send UX_SET_INTERFACE request with the alternate setting is selected to 1. I am attching screenshot for reference.

MicrosoftTeams-image (15).

could you please help on this.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Apr 05 '23 11:04 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

One more thing I have observed that when we run host application as VLC media player , I could see below error that to not immediatly after running VLC media player after some time this error is comming. MicrosoftTeams-image (17)

could you please help on this.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Apr 06 '23 07:04 MaheshAvula-Alifsemi

Hi @xiaocq2001 ,

I am have tested usb video class driver on window machine and used host application as VLC media player, sending UX_SET_INTERFACE request after(video probe control requests and commit control) with the alternate setting is selected to 0, but host app suppose to send UX_SET_INTERFACE request with the alternate setting is selected to 1 to use USB bandwidth to stream data. I would say that behaviour of my application is same on Windows machine as well as Linux machine, could you please help on this to move further, I am not understanding where it's going wrong.

Regards Mahesh Avula

MaheshAvula-Alifsemi avatar Apr 20 '23 05:04 MaheshAvula-Alifsemi

Here is something under windows for you to reference:

The USB traces as a whole: image

Get Cur/Max/Min content: image

xiaocq2001 avatar Apr 20 '23 10:04 xiaocq2001

@xiaocq2001 , Thank you so much for your inputs.

MaheshAvula-Alifsemi avatar Apr 21 '23 05:04 MaheshAvula-Alifsemi