Skip to content

Commit 26cb178

Browse files
committed
usb: uvc: allow the host to use short probe/commit messages
Some OSes like MacOS use shorter UVC 1.1 probe/commit messages even when UVC 1.5 is supported, without bUsage, bBitDepthLuma, bmSettings, bMaxNumberOfRefFramesPlus1, bmRateControlModes bmLayoutPerStream. Accept messages of arbitrary size to safely be processed, ignoring all missing fields, improving standard compliance. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent f66460b commit 26cb178

File tree

1 file changed

+20
-28
lines changed

1 file changed

+20
-28
lines changed

subsys/usb/device_next/class/usbd_uvc.c

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -694,27 +694,27 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
694694
const struct usb_setup_packet *const setup)
695695
{
696696
struct uvc_data *data = dev->data;
697-
size_t size = MIN(sizeof(struct uvc_probe), net_buf_tailroom(buf));
697+
const size_t size = MIN(sizeof(struct uvc_probe), net_buf_tailroom(buf));
698+
struct uvc_probe probe = {0};
698699
int ret;
699700

700701
switch (setup->bRequest) {
701702
case UVC_GET_INFO:
702703
if (size < 1) {
703704
return -ENOTSUP;
704705
}
706+
705707
net_buf_add_u8(buf, UVC_INFO_SUPPORTS_GET);
706708
return 0;
707709
case UVC_GET_LEN:
708710
if (size < 2) {
709711
return -ENOTSUP;
710712
}
713+
711714
net_buf_add_le16(buf, sizeof(struct uvc_probe));
712715
return 0;
713716
case UVC_GET_DEF:
714-
if (size < sizeof(struct uvc_probe)) {
715-
return -ENOTSUP;
716-
}
717-
net_buf_add_mem(buf, &data->default_probe, sizeof(data->default_probe));
717+
net_buf_add_mem(buf, &data->default_probe, size);
718718
return 0;
719719
case UVC_GET_MIN:
720720
__fallthrough;
@@ -723,16 +723,12 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
723723
case UVC_GET_MAX:
724724
__fallthrough;
725725
case UVC_GET_CUR:
726-
if (size < sizeof(struct uvc_probe)) {
727-
return -ENOTSUP;
728-
}
729-
730-
ret = uvc_get_vs_probe_struct(dev, (struct uvc_probe *)buf->data, setup->bRequest);
726+
ret = uvc_get_vs_probe_struct(dev, &probe, setup->bRequest);
731727
if (ret != 0) {
732728
return ret;
733729
}
734730

735-
net_buf_add(buf, sizeof(struct uvc_probe));
731+
net_buf_add_mem(buf, &probe, size);
736732
return 0;
737733
default:
738734
return -EINVAL;
@@ -742,45 +738,41 @@ static int uvc_get_vs_probe(const struct device *dev, struct net_buf *const buf,
742738
static int uvc_set_vs_probe(const struct device *dev, const struct net_buf *const buf)
743739
{
744740
struct uvc_data *data = dev->data;
745-
struct uvc_probe *probe;
741+
const size_t size = MIN(sizeof(struct uvc_probe), buf->len);
742+
struct uvc_probe probe = {0};
746743
struct uvc_probe max = {0};
747744
int ret;
748745

749-
if (buf->len != sizeof(*probe)) {
750-
LOG_ERR("Expected probe message of %u bytes got %u", sizeof(*probe), buf->len);
751-
return -EINVAL;
752-
}
753-
754-
probe = (struct uvc_probe *)buf->data;
746+
memcpy(&probe, buf->data, size);
755747

756748
ret = uvc_get_vs_probe_struct(dev, &max, UVC_GET_MAX);
757749
if (ret != 0) {
758750
return ret;
759751
}
760752

761-
if (probe->bFrameIndex > max.bFrameIndex) {
753+
if (probe.bFrameIndex > max.bFrameIndex) {
762754
LOG_WRN("The bFrameIndex %u requested is beyond the max %u",
763-
probe->bFrameIndex, max.bFrameIndex);
755+
probe.bFrameIndex, max.bFrameIndex);
764756
return -ERANGE;
765757
}
766758

767-
if (probe->bFormatIndex > max.bFormatIndex) {
759+
if (probe.bFormatIndex > max.bFormatIndex) {
768760
LOG_WRN("The bFormatIndex %u requested is beyond the max %u",
769-
probe->bFormatIndex, max.bFormatIndex);
761+
probe.bFormatIndex, max.bFormatIndex);
770762
return -ERANGE;
771763
}
772764

773-
if (probe->dwFrameInterval != 0) {
774-
data->video_frmival.numerator = sys_le32_to_cpu(probe->dwFrameInterval);
765+
if (probe.dwFrameInterval != 0) {
766+
data->video_frmival.numerator = sys_le32_to_cpu(probe.dwFrameInterval);
775767
data->video_frmival.denominator = USEC_PER_SEC * 100;
776768
}
777769

778-
if (probe->bFrameIndex != 0) {
779-
data->frame_id = probe->bFrameIndex;
770+
if (probe.bFrameIndex != 0) {
771+
data->frame_id = probe.bFrameIndex;
780772
}
781773

782-
if (probe->bFormatIndex != 0) {
783-
data->format_id = probe->bFormatIndex;
774+
if (probe.bFormatIndex != 0) {
775+
data->format_id = probe.bFormatIndex;
784776
}
785777

786778
return 0;

0 commit comments

Comments
 (0)