Skip to content

Commit 2d1409c

Browse files
committed
usb: uvc: allow the host to use short probe/commit messages
Some OSes like MacOS request only the UVC 1.1 probe/commit messages, and ignore the extra fields of the probe/commit struct: bUsage, bBitDepthLuma, bmSettings, bMaxNumberOfRefFramesPlus1, bmRateControlModes bmLayoutPerStream. Allow arbitrary size to safely be used by using a local `struct uvc_probe` and memcpy() the result from/to buffers. Given this is 48 bytes of temporary stack memory and control operation, performance and memory footprint are not observed. Signed-off-by: Josuah Demangeon <me@josuah.net>
1 parent 322da1d commit 2d1409c

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), net_buf_tailroom(buf));
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)