Merge pull request #1531 from pigrew/usbtmc_highspeed
USBTMC: Fixes and support for high-speed USB
This commit is contained in:
@@ -37,6 +37,9 @@
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||
|
||||
#define USB_VID 0xCafe
|
||||
#define USB_BCD 0x0200
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device Descriptors
|
||||
//--------------------------------------------------------------------+
|
||||
@@ -51,9 +54,9 @@ tusb_desc_device_t const desc_device =
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idVendor = USB_VID,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
.bcdDevice = USB_BCD,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
@@ -75,22 +78,22 @@ uint8_t const * tud_descriptor_device_cb(void)
|
||||
|
||||
#if defined(CFG_TUD_USBTMC)
|
||||
|
||||
# define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \
|
||||
# define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints, _bulkMaxPacketLength) \
|
||||
TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints, /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \
|
||||
TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */USBTMCD_MAX_PACKET_SIZE)
|
||||
TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */_bulkMaxPacketLength)
|
||||
|
||||
#if CFG_TUD_USBTMC_ENABLE_INT_EP
|
||||
// USBTMC Interrupt xfer always has length of 2, but we use epMaxSize=8 for
|
||||
// compatibility with mcus that only allow 8, 16, 32 or 64 for FS endpoints
|
||||
# define TUD_USBTMC_DESC(_itfnum) \
|
||||
TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \
|
||||
# define TUD_USBTMC_DESC(_itfnum, _bulkMaxPacketLength) \
|
||||
TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3, _bulkMaxPacketLength), \
|
||||
TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x82, /* epMaxSize = */ 8, /* bInterval = */16u )
|
||||
# define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN)
|
||||
|
||||
#else
|
||||
|
||||
# define TUD_USBTMC_DESC(_itfnum) \
|
||||
TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u)
|
||||
# define TUD_USBTMC_DESC(_itfnum, _bulkMaxPacketLength) \
|
||||
TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u, _bulkMaxPacketLength)
|
||||
# define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN)
|
||||
|
||||
#endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */
|
||||
@@ -119,21 +122,66 @@ enum
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
uint8_t const desc_fs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
TUD_USBTMC_DESC(ITF_NUM_USBTMC),
|
||||
TUD_USBTMC_DESC(ITF_NUM_USBTMC, /* _bulkMaxPacketLength = */ 64),
|
||||
};
|
||||
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
|
||||
uint8_t const desc_hs_configuration[] =
|
||||
{
|
||||
// Config number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
|
||||
|
||||
TUD_USBTMC_DESC(ITF_NUM_USBTMC, /* _bulkMaxPacketLength = */ 512),
|
||||
};
|
||||
|
||||
// other speed configuration
|
||||
uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
|
||||
|
||||
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
|
||||
tusb_desc_device_qualifier_t const desc_device_qualifier =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_qualifier_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
|
||||
.bcdUSB = USB_BCD,
|
||||
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
.bNumConfigurations = 0x01,
|
||||
.bReserved = 0x00
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete.
|
||||
// device_qualifier descriptor describes information about a high-speed capable device that would
|
||||
// change if the device were operating at the other speed. If not highspeed capable stall this request.
|
||||
uint8_t const* tud_descriptor_device_qualifier_cb(void)
|
||||
{
|
||||
return (uint8_t const*) &desc_device_qualifier;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
return desc_configuration;
|
||||
#if TUD_OPT_HIGH_SPEED
|
||||
// Although we are highspeed, host may be fullspeed.
|
||||
return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
|
||||
#else
|
||||
return desc_fs_configuration;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import visa
|
||||
import pyvisa
|
||||
import time
|
||||
import sys
|
||||
|
||||
@@ -54,9 +54,9 @@ def test_srq():
|
||||
assert (inst.read_stb() == 0)
|
||||
inst.write("123")
|
||||
|
||||
#inst.enable_event(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE)
|
||||
#waitrsp = inst.wait_on_event(visa.constants.VI_EVENT_SERVICE_REQ, 5000)
|
||||
#inst.discard_events(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE)
|
||||
#inst.enable_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
|
||||
#waitrsp = inst.wait_on_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, 5000)
|
||||
#inst.discard_events(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
|
||||
#inst.wait_for_srq()
|
||||
time.sleep(0.3)
|
||||
stb = inst.read_stb()
|
||||
@@ -77,8 +77,8 @@ def test_read_timeout():
|
||||
t0 = time.monotonic()
|
||||
try:
|
||||
rsp = inst.read()
|
||||
assert(false), "Read should have resulted in timeout"
|
||||
except visa.VisaIOError:
|
||||
assert(False), "Read should have resulted in timeout"
|
||||
except pyvisa.VisaIOError:
|
||||
print(" Got expected exception")
|
||||
t = time.monotonic() - t0
|
||||
assert ((t*1000.0) > (inst.timeout - 300))
|
||||
@@ -99,23 +99,27 @@ def test_abort_in():
|
||||
t0 = time.monotonic()
|
||||
try:
|
||||
rsp = inst.read()
|
||||
assert(false), "Read should have resulted in timeout"
|
||||
except visa.VisaIOError:
|
||||
assert(False), "Read should have resulted in timeout"
|
||||
except pyvisa.VisaIOError:
|
||||
print(" Got expected exception")
|
||||
t = time.monotonic() - t0
|
||||
assert ((t*1000.0) > (inst.timeout - 300))
|
||||
assert ((t*1000.0) < (inst.timeout + 300))
|
||||
print(f" Delay was {t:0.3}")
|
||||
# Response is still in queue, so send a clear (to be more helpful to the next test)
|
||||
# Response is still in queue, so read it out (to be more helpful to the next test)
|
||||
inst.timeout = 800
|
||||
y = inst.read()
|
||||
assert(y == "xxx\r\n")
|
||||
|
||||
def test_indicate():
|
||||
# perform indicator pulse
|
||||
usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM)
|
||||
usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
|
||||
retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=64, request_value=0x0000, index=usb_iface, length=0x0001)
|
||||
assert((retv[1] == visa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}"
|
||||
# pyvisa used to return (statuscode,bytes), but now only returns bytes, so we need to handle both cases
|
||||
if(isinstance(retv,bytes)):
|
||||
assert(retv == b'\x01')
|
||||
else:
|
||||
assert((retv[1] == pyvisa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}"
|
||||
|
||||
|
||||
def test_multi_read():
|
||||
@@ -131,19 +135,19 @@ def test_multi_read():
|
||||
#inst.chunk_size = old_chunk_size
|
||||
|
||||
def test_stall_ep0():
|
||||
usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM)
|
||||
usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
|
||||
inst.read_stb()
|
||||
# This is an invalid request, should create stall.
|
||||
try:
|
||||
retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=60, request_value=0x0000, index=usb_iface, length=0x0001)
|
||||
assert false
|
||||
except visa.VisaIOError:
|
||||
assert(False)
|
||||
except pyvisa.VisaIOError:
|
||||
pass
|
||||
|
||||
assert (inst.read_stb() == 0)
|
||||
|
||||
|
||||
rm = visa.ResourceManager()
|
||||
rm = pyvisa.ResourceManager()
|
||||
reslist = rm.list_resources("USB?::?*::INSTR")
|
||||
print(reslist)
|
||||
|
||||
@@ -167,7 +171,6 @@ inst.timeout = 2000
|
||||
print("+ multi read")
|
||||
test_multi_read()
|
||||
|
||||
|
||||
print("+ echo delay=0")
|
||||
inst.write("delay 0")
|
||||
test_echo(1,175)
|
||||
|
Reference in New Issue
Block a user