summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorJohn Keeping <john@metanate.com>2020-01-10 11:28:14 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-01-15 10:39:23 +0100
commit6b02af3465ee11b63a938b13bddbf7ecd92860f3 (patch)
treed44825ddb368775b2d5bc467ab44553b8e2871fb /drivers/usb/gadget
parent1e056efab9931366d1e1685736dfc978eca3bf06 (diff)
usb: gadget: f_uac2: fix packet size calculation
The packet size for USB audio must always be a multiple of the frame size, otherwise we are transmitting a partial frame which omits some channels (and these end up at the wrong offset in the next packet). Furthermore, it breaks the residue handling such that we end up trying to send a packet exceeding the maximum packet size for the endpoint. Signed-off-by: John Keeping <john@metanate.com> Signed-off-by: Felipe Balbi <balbi@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/function/u_audio.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index cf4f2358889b..6d956f190f5a 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -407,7 +407,7 @@ int u_audio_start_playback(struct g_audio *audio_dev)
struct usb_ep *ep;
struct uac_rtd_params *prm;
struct uac_params *params = &audio_dev->params;
- unsigned int factor, rate;
+ unsigned int factor;
const struct usb_endpoint_descriptor *ep_desc;
int req_len, i;
@@ -426,13 +426,15 @@ int u_audio_start_playback(struct g_audio *audio_dev)
/* pre-compute some values for iso_complete() */
uac->p_framesize = params->p_ssize *
num_channels(params->p_chmask);
- rate = params->p_srate * uac->p_framesize;
uac->p_interval = factor / (1 << (ep_desc->bInterval - 1));
- uac->p_pktsize = min_t(unsigned int, rate / uac->p_interval,
+ uac->p_pktsize = min_t(unsigned int,
+ uac->p_framesize *
+ (params->p_srate / uac->p_interval),
prm->max_psize);
if (uac->p_pktsize < prm->max_psize)
- uac->p_pktsize_residue = rate % uac->p_interval;
+ uac->p_pktsize_residue = uac->p_framesize *
+ (params->p_srate % uac->p_interval);
else
uac->p_pktsize_residue = 0;