From: Chris Wulff <crwulff@xxxxxxxxx> Moving this to allow it to be used by f_uac1 in the future. Signed-off-by: Chris Wulff <crwulff@xxxxxxxxx> --- 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 --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 */ -- 2.43.0