usb gadget0: ctrl write/read loopback tests
This is based on linux's gadget0 intel loopback tests, and also github pr: https://github.com/libopencm3/libopencm3/pull/592 Note that this captures the currently broken control loopback issues on dwc_otg devices. See https://github.com/libopencm3/libopencm3/issues/873 and all linked issues. Current status is passing on f3, f0, and failing on f4.
This commit is contained in:
parent
ebcf197810
commit
42e43515c6
|
@ -3,6 +3,7 @@ import datetime
|
|||
import random
|
||||
import usb.core
|
||||
import usb.util as uu
|
||||
import random
|
||||
import sys
|
||||
|
||||
import unittest
|
||||
|
@ -25,6 +26,8 @@ GZ_REQ_SET_ALIGNED=3
|
|||
GZ_REQ_SET_UNALIGNED=4
|
||||
GZ_REQ_WRITE_LOOPBACK_BUFFER=10
|
||||
GZ_REQ_READ_LOOPBACK_BUFFER=11
|
||||
GZ_REQ_INTEL_WRITE=0x5b
|
||||
GZ_REQ_INTEL_READ=0x5c
|
||||
|
||||
class find_by_serial(object):
|
||||
def __init__(self, serial):
|
||||
|
@ -83,6 +86,41 @@ class TestGadget0(unittest.TestCase):
|
|||
# Note, this might not be as portable as we'd like.
|
||||
self.assertIn("Pipe", e.strerror)
|
||||
|
||||
class TestIntelCompliance(unittest.TestCase):
|
||||
"""
|
||||
Part of intel's usb 2.0 compliance is writing and reading back control transfers
|
||||
"""
|
||||
def setUp(self):
|
||||
self.dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, custom_match=find_by_serial(DUT_SERIAL))
|
||||
self.assertIsNotNone(self.dev, "Couldn't find locm3 gadget0 device")
|
||||
|
||||
self.cfg = uu.find_descriptor(self.dev, bConfigurationValue=2)
|
||||
self.assertIsNotNone(self.cfg, "Config 2 should exist")
|
||||
self.dev.set_configuration(self.cfg)
|
||||
|
||||
def tearDown(self):
|
||||
uu.dispose_resources(self.dev)
|
||||
|
||||
def inner_t(self, mylen):
|
||||
data = [random.randrange(255) for x in range(mylen)]
|
||||
written = self.dev.ctrl_transfer(uu.CTRL_OUT | uu.CTRL_RECIPIENT_INTERFACE | uu.CTRL_TYPE_VENDOR, GZ_REQ_INTEL_WRITE, 0, 0, data)
|
||||
self.assertEqual(written, len(data), "Should have written all bytes plz")
|
||||
# now. in _theory_ I should be able to make a bulk transfer here and have it not "interfere"
|
||||
# fixme - try this out?
|
||||
read = self.dev.ctrl_transfer(uu.CTRL_IN | uu.CTRL_RECIPIENT_INTERFACE | uu.CTRL_TYPE_VENDOR, GZ_REQ_INTEL_READ, 0, 0, mylen)
|
||||
self.assertEqual(mylen, len(read))
|
||||
expected = array.array('B', [x for x in data])
|
||||
self.assertEqual(expected, read, "should have read back what we wrote")
|
||||
|
||||
def test_ctrl_loopbacks(self):
|
||||
self.inner_t(0)
|
||||
self.inner_t(10)
|
||||
self.inner_t(63)
|
||||
self.inner_t(64)
|
||||
self.inner_t(65)
|
||||
self.inner_t(140)
|
||||
self.inner_t(183)
|
||||
|
||||
|
||||
class TestConfigSourceSink(unittest.TestCase):
|
||||
"""
|
||||
|
|
|
@ -280,7 +280,6 @@ static enum usbd_request_return_codes gadget0_control_request(usbd_device *usbd_
|
|||
(void) usbd_dev;
|
||||
(void) complete;
|
||||
(void) buf;
|
||||
(void) len;
|
||||
ER_DPRINTF("ctrl breq: %x, bmRT: %x, windex :%x, wlen: %x, wval :%x\n",
|
||||
req->bRequest, req->bmRequestType, req->wIndex, req->wLength,
|
||||
req->wValue);
|
||||
|
@ -292,9 +291,31 @@ static enum usbd_request_return_codes gadget0_control_request(usbd_device *usbd_
|
|||
state.pattern = req->wValue;
|
||||
return USBD_REQ_HANDLED;
|
||||
case INTEL_COMPLIANCE_WRITE:
|
||||
case INTEL_COMPLIANCE_READ:
|
||||
ER_DPRINTF("unimplemented!");
|
||||
/* accept correctly formed ctrl writes */
|
||||
if (req->bmRequestType != (USB_REQ_TYPE_VENDOR|USB_REQ_TYPE_INTERFACE)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wValue || req->wIndex) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wLength > sizeof(usbd_control_buffer)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* ok, mark it as accepted. */
|
||||
return USBD_REQ_HANDLED;
|
||||
case INTEL_COMPLIANCE_READ:
|
||||
if (req->bmRequestType != (USB_REQ_TYPE_IN|USB_REQ_TYPE_VENDOR|USB_REQ_TYPE_INTERFACE)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wValue || req->wIndex) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
if (req->wLength > sizeof(usbd_control_buffer)) {
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
/* ok, return what they left there earlier */
|
||||
*len = req->wLength;
|
||||
return USBD_REQ_HANDLED;
|
||||
case GZ_REQ_SET_UNALIGNED:
|
||||
state.test_unaligned = 1;
|
||||
return USBD_REQ_HANDLED;
|
||||
|
@ -316,6 +337,9 @@ static enum usbd_request_return_codes gadget0_control_request(usbd_device *usbd_
|
|||
*len = req->wValue;
|
||||
}
|
||||
return USBD_REQ_HANDLED;
|
||||
default:
|
||||
ER_DPRINTF("Unhandled request!\n");
|
||||
return USBD_REQ_NOTSUPP;
|
||||
}
|
||||
return USBD_REQ_NEXT_CALLBACK;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue