From: Junjie Cao <[email protected]> A TD marked isochronous must become inactive on NAK. Send such a TD to the keyboard's interrupt endpoint, then inject a key and check that the inactive TD does not consume it. A new ordinary TD must still return that report.
Removing the isochronous ACTIVE-bit clearing in uhci_complete_td() fails this test. Signed-off-by: Junjie Cao <[email protected]> --- tests/qtest/usb-hcd-uhci-test.c | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/tests/qtest/usb-hcd-uhci-test.c b/tests/qtest/usb-hcd-uhci-test.c index 5c2b6cef7c..bad279e9a2 100644 --- a/tests/qtest/usb-hcd-uhci-test.c +++ b/tests/qtest/usb-hcd-uhci-test.c @@ -64,13 +64,17 @@ static uint32_t uhci_step(UHCITransferTest *t) } static void uhci_submit(UHCITransferTest *t, unsigned int pid, unsigned int ep, - unsigned int len, bool data1) + unsigned int len, bool data1, bool iso) { unsigned int i; - uint32_t ctrl = TD_CTRL_ACTIVE | TD_CTRL_IOC | 0x7ff | - (3 << TD_CTRL_ERROR_SHIFT); + uint32_t ctrl = TD_CTRL_ACTIVE | TD_CTRL_IOC | 0x7ff; uhci_writew(t, UHCI_USBCMD, 0); + if (iso) { + ctrl |= TD_CTRL_IOS; + } else { + ctrl |= 3 << TD_CTRL_ERROR_SHIFT; + } uhci_mem_writel(t, t->td, UHCI_LINK_END); uhci_mem_writel(t, t->td + 4, ctrl); uhci_mem_writel(t, t->td + 8, pid | (ep << 15) | (data1 << 19) | @@ -79,7 +83,8 @@ static void uhci_submit(UHCITransferTest *t, unsigned int pid, unsigned int ep, uhci_mem_writel(t, t->qh, UHCI_LINK_END); uhci_mem_writel(t, t->qh + 4, t->td); for (i = 0; i < 1024; i++) { - uhci_mem_writel(t, t->mem + 4 * i, t->qh | UHCI_LINK_QH); + uhci_mem_writel(t, t->mem + 4 * i, + iso ? t->td : t->qh | UHCI_LINK_QH); } uhci_writew(t, UHCI_USBSTS, UHCI_STS_USBINT | UHCI_STS_USBERR); uhci_writew(t, UHCI_USBCMD, UHCI_CMD_RS); @@ -133,15 +138,16 @@ static void uhci_transfer_init(UHCITransferTest *t) /* 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); + 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); + uhci_submit(t, UHCI_PID_IN, 0, 0, true, false); uhci_expect_complete(t, 0); } -static void test_uhci_nak(void) +static void test_uhci_nak(gconstpointer opaque) { const uint8_t expected[] = { 0, 0, 4, 0, 0, 0, 0, 0 }; + const bool iso = GPOINTER_TO_UINT(opaque); UHCITransferTest t; uint8_t report[sizeof(expected)]; uint32_t ctrl; @@ -149,11 +155,11 @@ static void test_uhci_nak(void) uhci_transfer_init(&t); qtest_memset(t.qs->qts, t.data, 0xa5, sizeof(report)); - uhci_submit(&t, UHCI_PID_IN, 1, sizeof(report), false); + uhci_submit(&t, UHCI_PID_IN, 1, sizeof(report), false, iso); for (i = 0; i < 3; i++) { ctrl = uhci_step(&t); g_assert_cmphex(ctrl & (TD_CTRL_ACTIVE | TD_CTRL_NAK), ==, - TD_CTRL_NAK | TD_CTRL_ACTIVE); + TD_CTRL_NAK | (iso ? 0 : TD_CTRL_ACTIVE)); g_assert_cmpuint((ctrl + 1) & 0x7ff, ==, 0); } qtest_memread(t.qs->qts, t.data, report, sizeof(report)); @@ -165,6 +171,15 @@ static void test_uhci_nak(void) "{'execute': 'input-send-event', 'arguments': {'events': [" "{'type': 'key', 'data': {'down': true, " "'key': {'type': 'qcode', 'data': 'a'}}}]}}"); + if (iso) { + /* An inactive isochronous TD must not consume the new report. */ + g_assert_cmphex(uhci_step(&t), ==, ctrl); + qtest_memread(t.qs->qts, t.data, report, sizeof(report)); + for (i = 0; i < sizeof(report); i++) { + g_assert_cmphex(report[i], ==, 0xa5); + } + uhci_submit(&t, UHCI_PID_IN, 1, sizeof(report), false, false); + } uhci_expect_complete(&t, sizeof(report)); qtest_memread(t.qs->qts, t.data, report, sizeof(report)); g_assert_cmpmem(report, sizeof(report), expected, sizeof(expected)); @@ -231,7 +246,10 @@ int main(int argc, char **argv) qtest_add_func("/uhci/pci/hotplug/usb-storage", test_usb_storage_hotplug); } if (qtest_has_device("usb-kbd")) { - qtest_add_func("/uhci/pci/intr-nak", test_uhci_nak); + qtest_add_data_func("/uhci/pci/intr-nak", GUINT_TO_POINTER(false), + test_uhci_nak); + qtest_add_data_func("/uhci/pci/iso-nak", GUINT_TO_POINTER(true), + test_uhci_nak); } if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { -- 2.43.0
