@@ -72,6 +72,7 @@ union uvc_fmt_desc {
7272 struct uvc_format_descriptor fmt ;
7373 struct uvc_format_uncomp_descriptor fmt_uncomp ;
7474 struct uvc_format_mjpeg_descriptor fmt_mjpeg ;
75+ struct uvc_format_frame_based_descriptor fmt_frame_based ;
7576 struct uvc_frame_descriptor frm ;
7677 struct uvc_frame_continuous_descriptor frm_cont ;
7778 struct uvc_frame_discrete_descriptor frm_disc ;
@@ -398,7 +399,8 @@ static void uvc_get_vs_fmtfrm_desc(const struct device *dev,
398399 i , desc -> bDescriptorSubtype , desc -> bFormatIndex , desc );
399400
400401 if ((desc -> bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED ||
401- desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ) &&
402+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ||
403+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_FRAME_BASED ) &&
402404 desc -> bFormatIndex == data -> format_id ) {
403405 * format_desc = desc ;
404406 break ;
@@ -413,7 +415,8 @@ static void uvc_get_vs_fmtfrm_desc(const struct device *dev,
413415 i , desc -> bDescriptorSubtype , desc -> bFrameIndex , desc );
414416
415417 if (desc -> bDescriptorSubtype != UVC_VS_FRAME_UNCOMPRESSED &&
416- desc -> bDescriptorSubtype != UVC_VS_FRAME_MJPEG ) {
418+ desc -> bDescriptorSubtype != UVC_VS_FRAME_MJPEG &&
419+ desc -> bDescriptorSubtype != UVC_VS_FRAME_FRAME_BASED ) {
417420 break ;
418421 }
419422
@@ -461,7 +464,8 @@ static int uvc_get_vs_probe_format_index(const struct device *dev, struct uvc_pr
461464 struct uvc_format_descriptor * desc = & cfg -> desc -> if1_fmts [i ].fmt ;
462465
463466 max += desc -> bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED ||
464- desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ;
467+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ||
468+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_FRAME_BASED ;
465469 }
466470
467471 switch (request ) {
@@ -496,8 +500,9 @@ static int uvc_get_vs_probe_frame_index(const struct device *dev, struct uvc_pro
496500 struct uvc_format_descriptor * desc = & cfg -> desc -> if1_fmts [i ].fmt ;
497501
498502 if ((desc -> bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED ||
499- desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ) &&
500- desc -> bFormatIndex == data -> format_id ) {
503+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ||
504+ desc -> bDescriptorSubtype == UVC_VS_FORMAT_FRAME_BASED ) &&
505+ desc -> bFormatIndex == data -> format_id ) {
501506 break ;
502507 }
503508 }
@@ -507,7 +512,8 @@ static int uvc_get_vs_probe_frame_index(const struct device *dev, struct uvc_pro
507512 struct uvc_frame_discrete_descriptor * desc = & cfg -> desc -> if1_fmts [i ].frm_disc ;
508513
509514 if (desc -> bDescriptorSubtype != UVC_VS_FRAME_UNCOMPRESSED &&
510- desc -> bDescriptorSubtype != UVC_VS_FRAME_MJPEG ) {
515+ desc -> bDescriptorSubtype != UVC_VS_FRAME_MJPEG &&
516+ desc -> bDescriptorSubtype != UVC_VS_FRAME_FRAME_BASED ) {
511517 break ;
512518 }
513519 max ++ ;
@@ -551,6 +557,13 @@ static int uvc_get_vs_probe_frame_interval(const struct device *dev, struct uvc_
551557 struct uvc_frame_discrete_descriptor * desc =
552558 (struct uvc_frame_discrete_descriptor * )frame_desc ;
553559
560+ min = sys_cpu_to_le32 (desc -> dwFrameInterval [0 ]);
561+ max_id = desc -> bFrameIntervalType - 1 ;
562+ max = sys_cpu_to_le32 (desc -> dwFrameInterval [max_id ]);
563+ } else if (frame_desc -> bDescriptorSubtype == UVC_VS_FRAME_FRAME_BASED ) {
564+ struct uvc_frame_based_discrete_descriptor * desc =
565+ (struct uvc_frame_based_discrete_descriptor * )frame_desc ;
566+
554567 min = sys_cpu_to_le32 (desc -> dwFrameInterval [0 ]);
555568 max_id = desc -> bFrameIntervalType - 1 ;
556569 max = sys_cpu_to_le32 (desc -> dwFrameInterval [max_id ]);
@@ -627,6 +640,15 @@ static int uvc_get_vs_format_from_desc(const struct device *dev, struct video_fo
627640
628641 LOG_DBG ("Found descriptor for format %u, frame %u, MJPEG" ,
629642 format_desc -> bFormatIndex , frame_desc -> bFrameIndex );
643+ } else if (format_desc -> bDescriptorSubtype == UVC_VS_FORMAT_FRAME_BASED ) {
644+ struct uvc_format_frame_based_descriptor * format_frame_based_desc =
645+ (void * )format_desc ;
646+
647+ fmt -> pixelformat = uvc_guid_to_fourcc (format_frame_based_desc -> guidFormat );
648+
649+ LOG_DBG ("Found descriptor for format %u, frame %u, GUID '%.4s', pixfmt %04x" ,
650+ format_frame_based_desc -> bFormatIndex , frame_desc -> bFrameIndex ,
651+ format_frame_based_desc -> guidFormat , fmt -> pixelformat );
630652 } else {
631653 struct uvc_format_uncomp_descriptor * format_uncomp_desc = (void * )format_desc ;
632654
@@ -1422,6 +1444,27 @@ static int uvc_add_vs_format_desc(const struct device *dev,
14221444 cfg -> desc -> if1_hdr .bNumFormats ++ ;
14231445 cfg -> desc -> if1_hdr .wTotalLength += desc -> bLength ;
14241446 * format_desc = (struct uvc_format_descriptor * )desc ;
1447+ } else if (fourcc == VIDEO_PIX_FMT_H264 ) {
1448+ struct uvc_format_frame_based_descriptor * desc ;
1449+
1450+ LOG_INF ("Adding format descriptor #%u for H264" ,
1451+ cfg -> desc -> if1_hdr .bNumFormats + 1 );
1452+
1453+ desc = & uvc_new_fmt_desc (dev )-> fmt_frame_based ;
1454+ if (desc == NULL ) {
1455+ return - ENOMEM ;
1456+ }
1457+
1458+ desc -> bDescriptorType = USB_DESC_CS_INTERFACE ;
1459+ desc -> bFormatIndex = cfg -> desc -> if1_hdr .bNumFormats + 1 ;
1460+ desc -> bLength = sizeof (* desc );
1461+ desc -> bDescriptorSubtype = UVC_VS_FORMAT_FRAME_BASED ;
1462+ uvc_fourcc_to_guid (desc -> guidFormat , fourcc );
1463+ desc -> bDefaultFrameIndex = 1 ;
1464+ desc -> bVariableSize = 1 ;
1465+ cfg -> desc -> if1_hdr .bNumFormats ++ ;
1466+ cfg -> desc -> if1_hdr .wTotalLength += desc -> bLength ;
1467+ * format_desc = (struct uvc_format_descriptor * )desc ;
14251468 } else {
14261469 struct uvc_format_uncomp_descriptor * desc ;
14271470
@@ -1502,6 +1545,19 @@ static int uvc_add_vs_frame_interval(struct uvc_frame_descriptor *const desc,
15021545 return - ENOMEM ;
15031546 }
15041547
1548+ frame_desc -> dwFrameInterval [frame_desc -> bFrameIntervalType ] =
1549+ sys_cpu_to_le32 (video_frmival_nsec (frmival ) / 100 );
1550+ frame_desc -> bFrameIntervalType ++ ;
1551+ frame_desc -> bLength += sizeof (uint32_t );
1552+ } else if (desc -> bDescriptorSubtype == UVC_VS_FRAME_FRAME_BASED ) {
1553+ struct uvc_frame_based_discrete_descriptor * frame_desc =
1554+ (struct uvc_frame_based_discrete_descriptor * )desc ;
1555+
1556+ if (frame_desc -> bFrameIntervalType >= CONFIG_USBD_VIDEO_MAX_FRMIVAL ) {
1557+ LOG_WRN ("Out of frame interval fields" );
1558+ return - ENOSPC ;
1559+ }
1560+
15051561 frame_desc -> dwFrameInterval [frame_desc -> bFrameIntervalType ] =
15061562 sys_cpu_to_le32 (video_frmival_nsec (frmival ) / 100 );
15071563 frame_desc -> bFrameIntervalType ++ ;
@@ -1544,8 +1600,13 @@ static int uvc_add_vs_frame_desc(const struct device *dev,
15441600 desc -> bFrameIndex = format_desc -> bNumFrameDescriptors + 1 ;
15451601 desc -> wWidth = sys_cpu_to_le16 (fmt -> width );
15461602 desc -> wHeight = sys_cpu_to_le16 (fmt -> height );
1547- desc -> bDescriptorSubtype = (format_desc -> bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED )
1548- ? UVC_VS_FRAME_UNCOMPRESSED : UVC_VS_FRAME_MJPEG ;
1603+ if (format_desc -> bDescriptorSubtype == UVC_VS_FORMAT_UNCOMPRESSED ) {
1604+ desc -> bDescriptorSubtype = UVC_VS_FRAME_UNCOMPRESSED ;
1605+ } else if (format_desc -> bDescriptorSubtype == UVC_VS_FORMAT_MJPEG ) {
1606+ desc -> bDescriptorSubtype = UVC_VS_FRAME_MJPEG ;
1607+ } else if (format_desc -> bDescriptorSubtype == UVC_VS_FORMAT_FRAME_BASED ) {
1608+ desc -> bDescriptorSubtype = UVC_VS_FRAME_FRAME_BASED ;
1609+ }
15491610 desc -> dwMinBitRate = sys_cpu_to_le32 (UINT32_MAX );
15501611 desc -> dwMaxBitRate = sys_cpu_to_le32 (0 );
15511612
@@ -1600,7 +1661,23 @@ static int uvc_add_vs_frame_desc(const struct device *dev,
16001661
16011662 /* UVC requires the frame intervals to be sorted, but not Zephyr */
16021663 qsort (frame_desc -> dwFrameInterval , frame_desc -> bFrameIntervalType ,
1603- sizeof (* frame_discrete_desc -> dwFrameInterval ), uvc_compare_frmival_desc );
1664+ sizeof (* frame_desc -> dwFrameInterval ), uvc_compare_frmival_desc );
1665+
1666+ frame_desc -> dwDefaultFrameInterval = frame_desc -> dwFrameInterval [0 ];
1667+ } else if (desc -> bDescriptorSubtype == UVC_VS_FRAME_FRAME_BASED ) {
1668+ struct uvc_frame_based_discrete_descriptor * frame_desc =
1669+ (struct uvc_frame_based_discrete_descriptor * )desc ;
1670+
1671+ /* If no frame intrval supported, default to 30 FPS */
1672+ if (frame_desc -> bFrameIntervalType == 0 ) {
1673+ struct video_frmival frmival = {.numerator = 1 , .denominator = 30 };
1674+
1675+ uvc_add_vs_frame_interval (desc , & frmival , fmt );
1676+ }
1677+
1678+ /* UVC requires the frame intervals to be sorted, but not Zephyr */
1679+ qsort (frame_desc -> dwFrameInterval , frame_desc -> bFrameIntervalType ,
1680+ sizeof (* frame_desc -> dwFrameInterval ), uvc_compare_frmival_desc );
16041681
16051682 frame_desc -> dwDefaultFrameInterval = frame_desc -> dwFrameInterval [0 ];
16061683 } else {
0 commit comments