summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2026-03-12 10:55:18 +0100
committerZixun LI <[email protected]>2026-03-12 10:55:18 +0100
commite2884a1b88ce89b6e724e3d3b441b8ee1f83c06c (patch)
treec322110908d4282ca7e37fe52dc9ce42be15b073 /test
parentc06dc871d651ddaf756afdc59ed148c4b1af314d (diff)
parentac61a5b176b44db503d8bcc287a622463b65e48e (diff)
Merge branch 'master' into ncm_restart
Diffstat (limited to 'test')
-rw-r--r--test/fuzz/device/cdc/src/tusb_config.h6
-rw-r--r--test/fuzz/device/msc/src/tusb_config.h6
-rw-r--r--test/fuzz/device/net/src/tusb_config.h6
-rw-r--r--test/fuzz/rules.mk1
-rwxr-xr-xtest/hil/hil_test.py140
-rw-r--r--test/hil/tinyusb.json3
6 files changed, 151 insertions, 11 deletions
diff --git a/test/fuzz/device/cdc/src/tusb_config.h b/test/fuzz/device/cdc/src/tusb_config.h
index 76f44619e..14b7b627d 100644
--- a/test/fuzz/device/cdc/src/tusb_config.h
+++ b/test/fuzz/device/cdc/src/tusb_config.h
@@ -101,8 +101,10 @@
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-// CDC Endpoint transfer buffer size, more is faster
-#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512
diff --git a/test/fuzz/device/msc/src/tusb_config.h b/test/fuzz/device/msc/src/tusb_config.h
index abd8cd4ce..7a4a24fb8 100644
--- a/test/fuzz/device/msc/src/tusb_config.h
+++ b/test/fuzz/device/msc/src/tusb_config.h
@@ -101,8 +101,10 @@
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-// CDC Endpoint transfer buffer size, more is faster
-#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512
diff --git a/test/fuzz/device/net/src/tusb_config.h b/test/fuzz/device/net/src/tusb_config.h
index 4fe98e043..de45e9ead 100644
--- a/test/fuzz/device/net/src/tusb_config.h
+++ b/test/fuzz/device/net/src/tusb_config.h
@@ -106,8 +106,10 @@
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-// CDC Endpoint transfer buffer size, more is faster
-#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
// MSC Buffer size of Device Mass storage
#define CFG_TUD_MSC_EP_BUFSIZE 512
diff --git a/test/fuzz/rules.mk b/test/fuzz/rules.mk
index b32f8d695..329dcce11 100644
--- a/test/fuzz/rules.mk
+++ b/test/fuzz/rules.mk
@@ -32,6 +32,7 @@ SRC_C += \
src/class/midi/midi_device.c \
src/class/msc/msc_device.c \
src/class/mtp/mtp_device.c \
+ src/class/printer/printer_device.c \
src/class/net/ecm_rndis_device.c \
src/class/net/ncm_device.c \
src/class/usbtmc/usbtmc_device.c \
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index b84740867..7cffd2da8 100755
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -153,19 +153,47 @@ def open_mtp_dev(uid):
# MTP seems to take a while to enumerate
timeout = 2 * ENUM_TIMEOUT
while timeout > 0:
- # run_cmd(f"gio mount -u mtp://TinyUsb_TinyUsb_Device_{uid}/")
+ # unmount gio/gvfs MTP mount which blocks libmtp from accessing the device
+ subprocess.run(f"gio mount -u mtp://TinyUsb_TinyUsb_Device_{uid}/",
+ shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
for raw in mtp.detect_devices():
mtp.device = mtp.mtp.LIBMTP_Open_Raw_Device(ctypes.byref(raw))
if mtp.device:
sn = mtp.get_serialnumber().decode('utf-8')
- #print(f'mtp serial = {sn}')
if sn == uid:
return mtp
+ mtp.disconnect()
time.sleep(1)
timeout -= 1
return None
+def get_printer_dev(id, vendor_str, product_str, ifnum):
+ """Find /dev/usb/lpX by matching USB serial, vendor, product, and interface number via sysfs"""
+ vendor_str = vendor_str.replace(' ', '_') if vendor_str else ''
+ product_str = product_str.replace(' ', '_') if product_str else ''
+ for lp in glob.glob('/sys/class/usbmisc/lp*'):
+ try:
+ sn = open(f'{lp}/device/../serial').read().strip()
+ if sn == id:
+ return f'/dev/usb/{os.path.basename(lp)}'
+ except (FileNotFoundError, PermissionError, ValueError):
+ pass
+ return None
+
+
+def open_printer_dev(id, vendor_str, product_str, ifnum):
+ """Wait for printer device to enumerate and return its path"""
+ timeout = ENUM_TIMEOUT
+ while timeout > 0:
+ lp_dev = get_printer_dev(id, vendor_str, product_str, ifnum)
+ if lp_dev and os.path.exists(lp_dev):
+ return lp_dev
+ time.sleep(1)
+ timeout -= 1
+ assert False, f'Printer device not found for {id} if{ifnum:02d}'
+
+
# -------------------------------------------------------------
# Flashing firmware
# -------------------------------------------------------------
@@ -302,7 +330,7 @@ def flash_esptool(board, firmware):
idf_target = json.load(f)['IDF_TARGET']
with open(f'{fw_dir}/flash_args') as f:
flash_args = f.read().strip().replace('\n', ' ')
- command = (f'esptool.py --chip {idf_target} -p {port} {flasher["args"]} '
+ command = (f'esptool --chip {idf_target} -p {port} {flasher["args"]} '
f'--before=default_reset --after=hard_reset write_flash {flash_args}')
ret = run_cmd(command, cwd=fw_dir)
return ret
@@ -552,6 +580,109 @@ def test_device_hid_composite_freertos(id):
pass
+def test_device_printer_to_cdc(board):
+ import threading
+
+ uid = board['uid']
+
+ # Wait for CDC port and printer device
+ cdc_port = get_serial_dev(uid, 'TinyUSB', "TinyUSB_Device", 0)
+ ser = open_serial_dev(cdc_port)
+ lp_dev = open_printer_dev(uid, 'TinyUSB', 'TinyUSB_Device', 2)
+
+ # Test 0: Verify IEEE 1284 Device ID from sysfs
+ expected_id = 'MFG:TinyUSB;MDL:Printer to CDC;CMD:PS;CLS:PRINTER;'
+ lp_name = os.path.basename(lp_dev)
+ sysfs_id_path = f'/sys/class/usbmisc/{lp_name}/device/ieee1284_id'
+ if os.path.exists(sysfs_id_path):
+ with open(sysfs_id_path) as f:
+ ieee1284_id = f.read().strip()
+ if ieee1284_id:
+ assert ieee1284_id == expected_id, (f'IEEE 1284 ID mismatch:\n'
+ f' expected: {expected_id}\n got: {ieee1284_id}')
+
+ def rand_ascii(length):
+ return "".join(random.choices(string.ascii_letters + string.digits, k=length)).encode("ascii")
+
+ sizes = [32, 64, 128, 256, 512, random.randint(2000, 5000)]
+
+ # flush any stale data
+ ser.reset_input_buffer()
+
+ # Test 1: Printer -> CDC with multiple sizes, write in random 1-64 byte chunks
+ for size in sizes:
+ test_data = rand_ascii(size)
+ ser.reset_input_buffer()
+ rd = b''
+ offset = 0
+ with open(lp_dev, 'wb') as lp:
+ while offset < size:
+ chunk_size = min(random.randint(1, 64), size - offset)
+ lp.write(test_data[offset:offset + chunk_size])
+ lp.flush()
+ rd += ser.read(chunk_size)
+ offset += chunk_size
+ # read any remaining bytes (fullspeed devices may need extra time)
+ while len(rd) < size:
+ remaining = ser.read(size - len(rd))
+ if not remaining:
+ break
+ rd += remaining
+ assert rd == test_data, (f'Printer->CDC wrong data ({size} bytes):\n'
+ f' expected: {test_data[:64]}\n received: {rd[:64]}')
+
+ # Test 2: CDC -> Printer with multiple sizes, write in random 1-64 byte chunks
+ # Use a thread to read from printer since /dev/usb/lp read blocks
+ ser.reset_input_buffer()
+ time.sleep(0.5)
+ for size in sizes:
+ test_data = rand_ascii(size)
+ rd_result = [b'', None] # [data, error]
+ reader_ready = threading.Event()
+
+ def lp_reader():
+ try:
+ rd = b''
+ fd = os.open(lp_dev, os.O_RDONLY)
+ reader_ready.set()
+ try:
+ while len(rd) < size:
+ chunk = os.read(fd, min(64, size - len(rd)))
+ if not chunk:
+ break
+ rd += chunk
+ finally:
+ os.close(fd)
+ rd_result[0] = rd
+ except Exception as e:
+ rd_result[1] = e
+ reader_ready.set()
+
+ reader = threading.Thread(target=lp_reader, daemon=True)
+ reader.start()
+ # wait for reader to open lp device before writing
+ reader_ready.wait(timeout=5)
+ time.sleep(0.1)
+
+ # Write to CDC in small chunks with flush to avoid overflowing device FIFO
+ offset = 0
+ while offset < size:
+ chunk_size = min(random.randint(1, 64), size - offset)
+ ser.write(test_data[offset:offset + chunk_size])
+ ser.flush()
+ time.sleep(0.01)
+ offset += chunk_size
+
+ reader.join(timeout=10)
+ assert not reader.is_alive(), f'CDC->Printer timeout ({size} bytes)'
+ assert rd_result[1] is None, f'CDC->Printer read error: {rd_result[1]}'
+ assert rd_result[0] == test_data, (f'CDC->Printer wrong data ({size} bytes):\n'
+ f' expected: {test_data[:64]}\n received: {rd_result[0][:64]}')
+ time.sleep(0.2)
+
+ ser.close()
+
+
def test_device_mtp(board):
uid = board['uid']
@@ -623,7 +754,8 @@ device_tests = [
'device/dfu_runtime',
'device/cdc_msc_freertos',
'device/hid_boot_interface',
- # 'device/mtp'
+ 'device/printer_to_cdc',
+ 'device/mtp'
]
dual_tests = [
diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json
index 7cb561b2d..029e5ffcd 100644
--- a/test/hil/tinyusb.json
+++ b/test/hil/tinyusb.json
@@ -13,7 +13,8 @@
"flasher": {
"name": "esptool",
"uid": "4ea4f48f6bc3ee11bbb9d00f9e1b1c54",
- "args": "-b 1500000"
+ "args": "-b 1500000",
+ "comment": "use --force for ESP32-P4 v0.1"
},
"comment": "Use TS3USB30 mux to test both device and host"
},