From: Junjie Cao <[email protected]> The isochronous NAK test exercises a TD sent to an interrupt endpoint. Add a successful transfer to an isochronous endpoint as a positive case for changes to endpoint type checks.
Configure a USB audio device and enable its streaming interface through EP0 before submitting an OUT packet. Check that the TD completes without errors and reports the full packet length. Signed-off-by: Junjie Cao <[email protected]> --- tests/qtest/usb-hcd-uhci-test.c | 74 +++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/tests/qtest/usb-hcd-uhci-test.c b/tests/qtest/usb-hcd-uhci-test.c index bad279e9a2..28d38bcc7c 100644 --- a/tests/qtest/usb-hcd-uhci-test.c +++ b/tests/qtest/usb-hcd-uhci-test.c @@ -21,6 +21,7 @@ static QOSState *qs; #define UHCI_FRAME_NS 1000000 #define UHCI_PID_SETUP 0x2d #define UHCI_PID_IN 0x69 +#define UHCI_PID_OUT 0xe1 #define UHCI_LINK_END 1 #define UHCI_LINK_QH 2 @@ -109,17 +110,27 @@ static void uhci_expect_complete(UHCITransferTest *t, unsigned int len) uhci_writew(t, UHCI_USBCMD, 0); } -static void uhci_transfer_init(UHCITransferTest *t) +static void uhci_control_no_data(UHCITransferTest *t, + const uint8_t setup[8]) +{ + qtest_memwrite(t->qs->qts, t->data, setup, 8); + uhci_submit(t, UHCI_PID_SETUP, 0, 8, false, false); + uhci_expect_complete(t, 8); + uhci_submit(t, UHCI_PID_IN, 0, 0, true, false); + uhci_expect_complete(t, 0); +} + +static void uhci_transfer_init(UHCITransferTest *t, const char *usb_device) { const char *cmd = "-nodefaults -global pci-host-bridge.bypass-iommu=on " - "-device piix3-usb-uhci,id=uhci,addr=1d.0 " - "-device usb-kbd,bus=uhci.0,port=1"; + "-device piix3-usb-uhci,id=uhci,addr=1d.0"; const uint8_t setup[] = { 0, 9, 1, 0, 0, 0, 0, 0 }; if (!strcmp(qtest_get_arch(), "ppc64")) { - t->qs = qtest_spapr_boot("%s", cmd); + t->qs = qtest_spapr_boot("%s %s", cmd, usb_device); } else { - t->qs = qtest_pc_boot("-machine pc,pit=off %s", cmd); + t->qs = qtest_pc_boot("-machine pc,pit=off %s %s", cmd, + usb_device); } qusb_pci_init_one(t->qs->pcibus, &t->hc, QPCI_DEVFN(0x1d, 0), 4); t->mem = guest_alloc(&t->qs->alloc, 0x3000); @@ -136,12 +147,8 @@ static void uhci_transfer_init(UHCITransferTest *t) UHCI_PORT_CCS | UHCI_PORT_EN); qpci_io_writel(t->hc.dev, t->hc.bar, UHCI_USBFLBASEADD, t->mem); - /* Configure the keyboard's interrupt endpoint through EP0 first. */ - qtest_memwrite(t->qs->qts, t->data, setup, sizeof(setup)); - uhci_submit(t, UHCI_PID_SETUP, 0, sizeof(setup), false, false); - uhci_expect_complete(t, sizeof(setup)); - uhci_submit(t, UHCI_PID_IN, 0, 0, true, false); - uhci_expect_complete(t, 0); + /* Configure the device through EP0 before using a non-default endpoint. */ + uhci_control_no_data(t, setup); } static void test_uhci_nak(gconstpointer opaque) @@ -153,7 +160,7 @@ static void test_uhci_nak(gconstpointer opaque) uint32_t ctrl; unsigned int i; - uhci_transfer_init(&t); + uhci_transfer_init(&t, "-device usb-kbd,bus=uhci.0,port=1"); qtest_memset(t.qs->qts, t.data, 0xa5, sizeof(report)); uhci_submit(&t, UHCI_PID_IN, 1, sizeof(report), false, iso); for (i = 0; i < 3; i++) { @@ -190,6 +197,48 @@ static void test_uhci_nak(gconstpointer opaque) qtest_shutdown(t.qs); } +static void test_uhci_iso_audio_out(void) +{ + const uint8_t set_interface[] = { 1, 11, 1, 0, 1, 0, 0, 0 }; + const unsigned int packet_size = 192; + UHCITransferTest t; + uint32_t ctrl; + unsigned int i; + + if (!qtest_has_device("usb-audio")) { + g_test_skip("usb-audio is not available"); + return; + } + + uhci_transfer_init(&t, "-audiodev none,id=snd0 " + "-device usb-audio,audiodev=snd0," + "bus=uhci.0,port=1"); + /* Interface 1, alternate setting 1 enables the stereo OUT endpoint. */ + uhci_control_no_data(&t, set_interface); + + /* Full-speed audio altsetting 1 advertises OUT endpoint 1, 192 bytes. */ + qtest_memset(t.qs->qts, t.data, 0x5a, packet_size); + uhci_submit(&t, UHCI_PID_OUT, 1, packet_size, false, true); + for (i = 0; i < 10; i++) { + ctrl = uhci_step(&t); + if (!(ctrl & TD_CTRL_ACTIVE)) { + break; + } + } + g_assert_cmpuint(i, <, 10); + g_assert_cmphex(ctrl & (TD_CTRL_ACTIVE | TD_CTRL_STALL | TD_CTRL_BABBLE | + TD_CTRL_NAK | TD_CTRL_TIMEOUT), ==, 0); + g_assert_cmpuint((ctrl + 1) & 0x7ff, ==, packet_size); + g_assert_cmphex(qpci_io_readw(t.hc.dev, t.hc.bar, UHCI_USBSTS) & + UHCI_STS_USBINT, ==, UHCI_STS_USBINT); + uhci_writew(&t, UHCI_USBCMD, 0); + + qpci_iounmap(t.hc.dev, t.hc.bar); + uhci_deinit(&t.hc); + guest_free(&t.qs->alloc, t.mem); + qtest_shutdown(t.qs); +} + static void test_port(int port) { struct qhc uhci; @@ -251,6 +300,7 @@ int main(int argc, char **argv) qtest_add_data_func("/uhci/pci/iso-nak", GUINT_TO_POINTER(true), test_uhci_nak); } + qtest_add_func("/uhci/pci/iso-audio-out", test_uhci_iso_audio_out); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { qs = qtest_pc_boot("%s", cmd); -- 2.43.0
