Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107197288
D28032.id85941.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D28032.id85941.diff
View Options
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -945,6 +945,31 @@
return (0);
}
+static usb_error_t
+uaudio_set_alt_interface_index(struct uaudio_softc *sc, uint8_t iface_index, uint8_t alt_index)
+{
+ struct usb_interface *iface;
+ usb_error_t err;
+
+ iface = usbd_get_iface(sc->sc_udev, iface_index);
+ if (iface == NULL || iface->idesc == NULL)
+ return (USB_ERR_INVAL);
+
+ /* check if correct alternate setting is already selected */
+ if (iface->alt_index == alt_index) {
+ if (alt_index == 0) {
+ /* force power save mode by selecting default alternate setting */
+ err = usbd_req_set_alt_interface_no(sc->sc_udev, NULL, iface_index,
+ iface->idesc->bAlternateSetting);
+ } else {
+ err = USB_ERR_NORMAL_COMPLETION;
+ }
+ } else {
+ err = usbd_set_alt_interface_index(sc->sc_udev, iface_index, alt_index);
+ }
+ return (err);
+}
+
static int
uaudio_attach(device_t dev)
{
@@ -1019,16 +1044,16 @@
/*
* Need to set a default alternate interface, else
- * some USB audio devices might go into an infinte
+ * some USB audio devices might go into an infinite
* re-enumeration loop:
*/
- err = usbd_set_alt_interface_index(sc->sc_udev,
- sc->sc_play_chan[i].usb_alt[0].iface_index,
- sc->sc_play_chan[i].usb_alt[0].iface_alt_index);
+ err = uaudio_set_alt_interface_index(sc,
+ sc->sc_play_chan[i].usb_alt[0].iface_index, 0);
if (err) {
DPRINTF("setting of alternate index failed: %s!\n",
usbd_errstr(err));
}
+
for (x = 0; x != sc->sc_play_chan[i].num_alt; x++) {
device_printf(dev, "Play[%u]: %d Hz, %d ch, %s format, "
"2x%dms buffer.\n", i,
@@ -1049,16 +1074,16 @@
/*
* Need to set a default alternate interface, else
- * some USB audio devices might go into an infinte
+ * some USB audio devices might go into an infinite
* re-enumeration loop:
*/
- err = usbd_set_alt_interface_index(sc->sc_udev,
- sc->sc_rec_chan[i].usb_alt[0].iface_index,
- sc->sc_rec_chan[i].usb_alt[0].iface_alt_index);
+ err = uaudio_set_alt_interface_index(sc,
+ sc->sc_rec_chan[i].usb_alt[0].iface_index, 0);
if (err) {
DPRINTF("setting of alternate index failed: %s!\n",
usbd_errstr(err));
}
+
for (x = 0; x != sc->sc_rec_chan[i].num_alt; x++) {
device_printf(dev, "Record[%u]: %d Hz, %d ch, %s format, "
"2x%dms buffer.\n", i,
@@ -1307,7 +1332,7 @@
uint32_t frames;
uint32_t buf_size;
uint16_t fps;
- uint8_t set_alt;
+ uint8_t next_alt;
uint8_t fps_shift;
uint8_t operation;
usb_error_t err;
@@ -1319,24 +1344,54 @@
usb_proc_explore_lock(sc->sc_udev);
operation = chan->operation;
- chan->operation = CHAN_OP_NONE;
+ switch (operation) {
+ case CHAN_OP_START:
+ case CHAN_OP_STOP:
+ chan->operation = CHAN_OP_NONE;
+ break;
+ default:
+ break;
+ }
usb_proc_explore_unlock(sc->sc_udev);
- mtx_lock(chan->pcm_mtx);
- if (chan->cur_alt != chan->set_alt)
- set_alt = chan->set_alt;
- else
- set_alt = CHAN_MAX_ALT;
- mtx_unlock(chan->pcm_mtx);
+ switch (operation) {
+ case CHAN_OP_DRAIN:
+ case CHAN_OP_STOP:
+ /* Unsetup prior USB transfers, if any. */
+ usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1);
- if (set_alt >= chan->num_alt)
- goto done;
+ mtx_lock(chan->pcm_mtx);
+ chan->cur_alt = CHAN_MAX_ALT;
+ mtx_unlock(chan->pcm_mtx);
- chan_alt = chan->usb_alt + set_alt;
+ /*
+ * The first alternate setting is typically used for
+ * power saving mode. Set this alternate setting as
+ * part of entering stop.
+ */
+ err = uaudio_set_alt_interface_index(sc, chan->iface_index, 0);
+ if (err) {
+ DPRINTF("setting of default alternate index failed: %s!\n",
+ usbd_errstr(err));
+ }
+ return;
- usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1);
+ case CHAN_OP_START:
+ /* Unsetup prior USB transfers, if any. */
+ usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1);
+ break;
+
+ default:
+ return;
+ }
+
+ mtx_lock(chan->pcm_mtx);
+ next_alt = chan->set_alt;
+ mtx_unlock(chan->pcm_mtx);
+
+ chan_alt = chan->usb_alt + next_alt;
- err = usbd_set_alt_interface_index(sc->sc_udev,
+ err = uaudio_set_alt_interface_index(sc,
chan_alt->iface_index, chan_alt->iface_alt_index);
if (err) {
DPRINTF("setting of alternate index failed: %s!\n",
@@ -1438,32 +1493,16 @@
goto error;
}
- mtx_lock(chan->pcm_mtx);
- chan->cur_alt = set_alt;
- mtx_unlock(chan->pcm_mtx);
-
-done:
#if (UAUDIO_NCHANBUFS != 2)
-#error "please update code"
+#error "Please update code below!"
#endif
- switch (operation) {
- case CHAN_OP_START:
- mtx_lock(chan->pcm_mtx);
- usbd_transfer_start(chan->xfer[0]);
- usbd_transfer_start(chan->xfer[1]);
- mtx_unlock(chan->pcm_mtx);
- break;
- case CHAN_OP_STOP:
- mtx_lock(chan->pcm_mtx);
- usbd_transfer_stop(chan->xfer[0]);
- usbd_transfer_stop(chan->xfer[1]);
- mtx_unlock(chan->pcm_mtx);
- break;
- default:
- break;
- }
- return;
+ mtx_lock(chan->pcm_mtx);
+ chan->cur_alt = next_alt;
+ usbd_transfer_start(chan->xfer[0]);
+ usbd_transfer_start(chan->xfer[1]);
+ mtx_unlock(chan->pcm_mtx);
+ return;
error:
usbd_transfer_unsetup(chan->xfer, UAUDIO_NCHANBUFS + 1);
@@ -2746,27 +2785,24 @@
}
static void
-uaudio_chan_start_sub(struct uaudio_chan *ch)
+uaudio_chan_reconfigure(struct uaudio_chan *ch, uint8_t operation)
{
struct uaudio_softc *sc = ch->priv_sc;
- int do_start = 0;
-
- if (ch->operation != CHAN_OP_DRAIN) {
- if (ch->cur_alt == ch->set_alt &&
- ch->operation == CHAN_OP_NONE &&
- mtx_owned(ch->pcm_mtx) != 0) {
- /* save doing the explore task */
- do_start = 1;
- } else {
- ch->operation = CHAN_OP_START;
- (void)usb_proc_explore_msignal(sc->sc_udev,
- &sc->sc_config_msg[0], &sc->sc_config_msg[1]);
- }
- }
- if (do_start) {
- usbd_transfer_start(ch->xfer[0]);
- usbd_transfer_start(ch->xfer[1]);
- }
+
+ /* Check for shutdown. */
+ if (ch->operation == CHAN_OP_DRAIN)
+ return;
+
+ /* Set next operation. */
+ ch->operation = operation;
+
+ /*
+ * Because changing the alternate setting modifies the USB
+ * configuration, this part must be executed from the USB
+ * explore process.
+ */
+ (void)usb_proc_explore_msignal(sc->sc_udev,
+ &sc->sc_config_msg[0], &sc->sc_config_msg[1]);
}
static int
@@ -2819,10 +2855,10 @@
* Start both endpoints because of need for
* jitter information:
*/
- uaudio_chan_start_sub(&sc->sc_rec_chan[i]);
- uaudio_chan_start_sub(&sc->sc_play_chan[i]);
+ uaudio_chan_reconfigure(&sc->sc_rec_chan[i], CHAN_OP_START);
+ uaudio_chan_reconfigure(&sc->sc_play_chan[i], CHAN_OP_START);
} else {
- uaudio_chan_start_sub(ch);
+ uaudio_chan_reconfigure(ch, CHAN_OP_START);
}
}
@@ -2830,30 +2866,6 @@
usb_proc_explore_unlock(sc->sc_udev);
}
-static void
-uaudio_chan_stop_sub(struct uaudio_chan *ch)
-{
- struct uaudio_softc *sc = ch->priv_sc;
- int do_stop = 0;
-
- if (ch->operation != CHAN_OP_DRAIN) {
- if (ch->cur_alt == ch->set_alt &&
- ch->operation == CHAN_OP_NONE &&
- mtx_owned(ch->pcm_mtx) != 0) {
- /* save doing the explore task */
- do_stop = 1;
- } else {
- ch->operation = CHAN_OP_STOP;
- (void)usb_proc_explore_msignal(sc->sc_udev,
- &sc->sc_config_msg[0], &sc->sc_config_msg[1]);
- }
- }
- if (do_stop) {
- usbd_transfer_stop(ch->xfer[0]);
- usbd_transfer_stop(ch->xfer[1]);
- }
-}
-
void
uaudio_chan_stop(struct uaudio_chan *ch)
{
@@ -2882,10 +2894,10 @@
* Stop both endpoints in case the one was used for
* jitter information:
*/
- uaudio_chan_stop_sub(&sc->sc_rec_chan[i]);
- uaudio_chan_stop_sub(&sc->sc_play_chan[i]);
+ uaudio_chan_reconfigure(&sc->sc_rec_chan[i], CHAN_OP_STOP);
+ uaudio_chan_reconfigure(&sc->sc_play_chan[i], CHAN_OP_STOP);
} else {
- uaudio_chan_stop_sub(ch);
+ uaudio_chan_reconfigure(ch, CHAN_OP_STOP);
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jan 12, 12:52 PM (20 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15769522
Default Alt Text
D28032.id85941.diff (7 KB)
Attached To
Mode
D28032: Set default alternate setting when USB audio devices are not in use, to activate power save features.
Attached
Detach File
Event Timeline
Log In to Comment