diff mbox series

[RFC,04/14] usb: gadget: f_uac2: Move max packet size code to a common header

Message ID 20240928150905.2616313-5-crwulff@gmail.com
State New
Headers show
Series usb: gadget: f_uac: Add support for alt mode settings | expand

Commit Message

Chris Wulff Sept. 28, 2024, 3:08 p.m. UTC
From: Chris Wulff <crwulff@gmail.com>

Moving this to allow it to be used by f_uac1 in the future.

Signed-off-by: Chris Wulff <crwulff@gmail.com>
---
 drivers/usb/gadget/function/f_uac2.c      | 116 ++--------------------
 drivers/usb/gadget/function/u_uac_utils.h | 111 +++++++++++++++++++++
 2 files changed, 122 insertions(+), 105 deletions(-)
diff mbox series

Patch

diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 2142a0951f71..050789d2d3c9 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -112,16 +112,6 @@  enum {
 
 static struct usb_string strings_fn[NUM_STR_DESCRIPTORS + 1] = {};
 
-static const char *const speed_names[] = {
-	[USB_SPEED_UNKNOWN] = "UNKNOWN",
-	[USB_SPEED_LOW] = "LS",
-	[USB_SPEED_FULL] = "FS",
-	[USB_SPEED_HIGH] = "HS",
-	[USB_SPEED_WIRELESS] = "W",
-	[USB_SPEED_SUPER] = "SS",
-	[USB_SPEED_SUPER_PLUS] = "SS+",
-};
-
 static struct usb_gadget_strings str_fn = {
 	.language = 0x0409,	/* en-us */
 	.strings = strings_fn,
@@ -656,113 +646,29 @@  struct cntrl_subrange_lay3 {
 
 DECLARE_UAC2_CNTRL_RANGES_LAY3(srates, UAC_MAX_RATES);
 
-static int get_max_srate(const int *srates)
-{
-	int i, max_srate = 0;
-
-	for (i = 0; i < UAC_MAX_RATES; i++) {
-		if (srates[i] == 0)
-			break;
-		if (srates[i] > max_srate)
-			max_srate = srates[i];
-	}
-	return max_srate;
-}
-
-static int get_max_bw_for_bint(const struct f_uac2_opts *uac2_opts,
-	u8 bint, unsigned int factor, bool is_playback)
+static int set_ep_max_packet_size_bint(struct device *dev, const struct f_uac2_opts *uac2_opts,
+	struct usb_endpoint_descriptor *ep_desc,
+	enum usb_device_speed speed, bool is_playback)
 {
-	int chmask, srate, ssize;
-	u16 max_size_bw;
+	int chmask, srate, ssize, hs_bint, sync;
 
 	if (is_playback) {
 		chmask = uac2_opts->p_chmask;
 		srate = get_max_srate(uac2_opts->p_srates);
 		ssize = uac2_opts->p_ssize;
+		hs_bint = uac2_opts->p_hs_bint;
+		sync = USB_ENDPOINT_SYNC_ASYNC;
 	} else {
 		chmask = uac2_opts->c_chmask;
 		srate = get_max_srate(uac2_opts->c_srates);
 		ssize = uac2_opts->c_ssize;
+		hs_bint = uac2_opts->c_hs_bint;
+		sync = uac2_opts->c_sync;
 	}
 
-	if (is_playback || (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC)) {
-		// playback is always async, capture only when configured
-		// Win10 requires max packet size + 1 frame
-		srate = srate * (1000 + uac2_opts->fb_max) / 1000;
-		// updated srate is always bigger, therefore DIV_ROUND_UP always yields +1
-		max_size_bw = num_channels(chmask) * ssize *
-			(DIV_ROUND_UP(srate, factor / (1 << (bint - 1))));
-	} else {
-		// adding 1 frame provision for Win10
-		max_size_bw = num_channels(chmask) * ssize *
-			(DIV_ROUND_UP(srate, factor / (1 << (bint - 1))) + 1);
-	}
-	return max_size_bw;
-}
-
-static int set_ep_max_packet_size_bint(struct device *dev, const struct f_uac2_opts *uac2_opts,
-	struct usb_endpoint_descriptor *ep_desc,
-	enum usb_device_speed speed, bool is_playback)
-{
-	u16 max_size_bw, max_size_ep;
-	u8 bint, opts_bint;
-	char *dir;
-
-	switch (speed) {
-	case USB_SPEED_FULL:
-		max_size_ep = 1023;
-		// fixed
-		bint = ep_desc->bInterval;
-		max_size_bw = get_max_bw_for_bint(uac2_opts, bint, 1000, is_playback);
-		break;
-
-	case USB_SPEED_HIGH:
-	case USB_SPEED_SUPER:
-		max_size_ep = 1024;
-		if (is_playback)
-			opts_bint = uac2_opts->p_hs_bint;
-		else
-			opts_bint = uac2_opts->c_hs_bint;
-
-		if (opts_bint > 0) {
-			/* fixed bint */
-			bint = opts_bint;
-			max_size_bw = get_max_bw_for_bint(uac2_opts, bint, 8000, is_playback);
-		} else {
-			/* checking bInterval from 4 to 1 whether the required bandwidth fits */
-			for (bint = 4; bint > 0; --bint) {
-				max_size_bw = get_max_bw_for_bint(
-					uac2_opts, bint, 8000, is_playback);
-				if (max_size_bw <= max_size_ep)
-					break;
-			}
-		}
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (is_playback)
-		dir = "Playback";
-	else
-		dir = "Capture";
-
-	if (max_size_bw <= max_size_ep)
-		dev_dbg(dev,
-			"%s %s: Would use wMaxPacketSize %d and bInterval %d\n",
-			speed_names[speed], dir, max_size_bw, bint);
-	else {
-		dev_warn(dev,
-			"%s %s: Req. wMaxPacketSize %d at bInterval %d > max ISOC %d, may drop data!\n",
-			speed_names[speed], dir, max_size_bw, bint, max_size_ep);
-		max_size_bw = max_size_ep;
-	}
-
-	ep_desc->wMaxPacketSize = cpu_to_le16(max_size_bw);
-	ep_desc->bInterval = bint;
-
-	return 0;
+	return uac_set_ep_max_packet_size_bint(
+		dev, ep_desc, speed, is_playback, hs_bint, chmask,
+		srate, ssize, sync, uac2_opts->fb_max);
 }
 
 static struct uac2_feature_unit_descriptor *build_fu_desc(int chmask)
diff --git a/drivers/usb/gadget/function/u_uac_utils.h b/drivers/usb/gadget/function/u_uac_utils.h
index 5f88e31103dd..7ef9f699657c 100644
--- a/drivers/usb/gadget/function/u_uac_utils.h
+++ b/drivers/usb/gadget/function/u_uac_utils.h
@@ -214,4 +214,115 @@  end:									\
 									\
 CONFIGFS_ATTR(prefix##_, name)
 
+/*
+ * Functions for EP interval and max packet size
+ */
+
+static const char *const speed_names[] = {
+	[USB_SPEED_UNKNOWN] = "UNKNOWN",
+	[USB_SPEED_LOW] = "LS",
+	[USB_SPEED_FULL] = "FS",
+	[USB_SPEED_HIGH] = "HS",
+	[USB_SPEED_WIRELESS] = "W",
+	[USB_SPEED_SUPER] = "SS",
+	[USB_SPEED_SUPER_PLUS] = "SS+",
+};
+
+static int get_max_srate(const int *srates)
+{
+	int i, max_srate = 0;
+
+	for (i = 0; i < UAC_MAX_RATES; i++) {
+		if (srates[i] == 0)
+			break;
+		if (srates[i] > max_srate)
+			max_srate = srates[i];
+	}
+	return max_srate;
+}
+
+static int get_max_bw_for_bint(u8 bint, unsigned int factor, int chmask,
+			       int srate, int ssize, int sync, int fb_max)
+{
+	u16 max_size_bw;
+
+	if (sync == USB_ENDPOINT_SYNC_ASYNC) {
+		// playback is always async, capture only when configured
+		// Win10 requires max packet size + 1 frame
+		srate = srate * (1000 + fb_max) / 1000;
+		// updated srate is always bigger, therefore DIV_ROUND_UP always yields +1
+		max_size_bw = num_channels(chmask) * ssize *
+			(DIV_ROUND_UP(srate, factor / (1 << (bint - 1))));
+	} else {
+		// adding 1 frame provision for Win10
+		max_size_bw = num_channels(chmask) * ssize *
+			(DIV_ROUND_UP(srate, factor / (1 << (bint - 1))) + 1);
+	}
+	return max_size_bw;
+}
+
+static int uac_set_ep_max_packet_size_bint(struct device *dev,
+	struct usb_endpoint_descriptor *ep_desc,
+	enum usb_device_speed speed, bool is_playback, int hs_bint,
+	int chmask, int srate, int ssize, int sync, int fb_max)
+{
+	u16 max_size_bw, max_size_ep;
+	u8 bint;
+	char *dir;
+
+	switch (speed) {
+	case USB_SPEED_FULL:
+		max_size_ep = 1023;
+		// fixed
+		bint = ep_desc->bInterval;
+		max_size_bw = get_max_bw_for_bint(bint, 1000, chmask, srate,
+						  ssize, sync, fb_max);
+		break;
+
+	case USB_SPEED_HIGH:
+	case USB_SPEED_SUPER:
+		max_size_ep = 1024;
+		if (hs_bint > 0) {
+			/* fixed bint */
+			bint = hs_bint;
+			max_size_bw = get_max_bw_for_bint(bint, 8000, chmask, srate,
+							  ssize, sync, fb_max);
+		} else {
+			/* checking bInterval from 4 to 1 whether the required bandwidth fits */
+			for (bint = 4; bint > 0; --bint) {
+				max_size_bw = get_max_bw_for_bint(
+					bint, 8000, chmask, srate,
+					ssize, sync, fb_max);
+				if (max_size_bw <= max_size_ep)
+					break;
+			}
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (is_playback)
+		dir = "Playback";
+	else
+		dir = "Capture";
+
+	if (max_size_bw <= max_size_ep)
+		dev_dbg(dev,
+			"%s %s: Would use wMaxPacketSize %d and bInterval %d\n",
+			speed_names[speed], dir, max_size_bw, bint);
+	else {
+		dev_warn(dev,
+			"%s %s: Req. wMaxPacketSize %d at bInterval %d > max ISOC %d, may drop data!\n",
+			speed_names[speed], dir, max_size_bw, bint, max_size_ep);
+		max_size_bw = max_size_ep;
+	}
+
+	ep_desc->wMaxPacketSize = cpu_to_le16(max_size_bw);
+	ep_desc->bInterval = bint;
+
+	return 0;
+}
+
 #endif	/* __U_UAC_UTILS_H */