summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Elder <paul.elder@ideasonboard.com>2018-09-02 19:46:03 -0400
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2018-09-24 19:06:53 +0300
commit89969a842e72b1b653140a4bbddd927b242736d0 (patch)
tree779b569b1fe0b4819700a8e930ab6338b4c29bbf
parentcb2200f7af8341aaf0c6abd7ba37e4c667c41639 (diff)
downloadlinux-89969a842e72b1b653140a4bbddd927b242736d0.tar.bz2
usb: gadget: uvc: configfs: Sort frame intervals upon writing
There is an issue where the host is unable to tell the gadget what frame rate it wants if the dwFrameIntervals in the interface descriptors are not in ascending order. This means that when instantiating a uvc gadget via configfs the user must make sure the dwFrameIntervals are in ascending order. Instead of silently failing the breaking of this rule, we sort the dwFrameIntervals upon writing to configfs. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 799dc32c5bc7..6031467f1868 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -9,6 +9,9 @@
*
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
*/
+
+#include <linux/sort.h>
+
#include "u_uvc.h"
#include "uvc_configfs.h"
@@ -35,6 +38,14 @@ static struct configfs_attribute prefix##attr_##cname = { \
.show = prefix##cname##_show, \
}
+static int uvcg_config_compare_u32(const void *l, const void *r)
+{
+ u32 li = *(const u32 *)l;
+ u32 ri = *(const u32 *)r;
+
+ return li < ri ? -1 : li == ri ? 0 : 1;
+}
+
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_uvc_opts,
@@ -1325,6 +1336,8 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
kfree(ch->dw_frame_interval);
ch->dw_frame_interval = frm_intrv;
ch->frame.b_frame_interval_type = n;
+ sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
+ uvcg_config_compare_u32, NULL);
ret = len;
end: