case USB_ST_SETUP: /* - * Check if the recording stream can be used as a - * source of jitter information to save some - * isochronous bandwidth: + * Submit the transfer even when the recording stream + * provides the jitter information, so that the feedback + * rate keeps being sampled for diagnostic purposes. */ - if (ch->priv_sc->sc_rec_chan[i].num_alt != 0 && - uaudio_debug == 0) - break; usbd_xfer_set_frames(xfer, 1); usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_framelen(xfer)); usbd_transfer_submit(xfer); @@ -2884,12 +2950,33 @@ uaudio_chan_start(struct uaudio_chan *ch) if (uaudio_chan_need_both( &sc->sc_play_chan[i], &sc->sc_rec_chan[i])) { + struct uaudio_chan *ch_play = &sc->sc_play_chan[i]; + struct uaudio_chan *ch_rec = &sc->sc_rec_chan[i]; + uint8_t rec_alt; + + /* + * The recording channel is only being started as a + * source of jitter information for the playback + * stream. Align its nominal rate with the + * playback rate so that (a) it does not reprogram + * a sample clock shared with the playback path to + * a conflicting rate, and (b) its expected frame + * sizes match what the device actually produces, + * keeping the derived jitter information valid. + * The USB explore lock is held here, which also + * serializes against uaudio_chan_set_param_speed(). + */ + if (uaudio_chan_match_rate(ch_rec, + ch_play->usb_alt[ch_play->set_alt].sample_rate, + &rec_alt)) + ch_rec->set_alt = rec_alt; + /* * Start both endpoints because of need for * jitter information: */ - uaudio_chan_reconfigure(&sc->sc_rec_chan[i], CHAN_OP_START); - uaudio_chan_reconfigure(&sc->sc_play_chan[i], CHAN_OP_START); + uaudio_chan_reconfigure(ch_rec, CHAN_OP_START); + uaudio_chan_reconfigure(ch_play, CHAN_OP_START); } else { uaudio_chan_reconfigure(ch, CHAN_OP_START); }