summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-03-11 13:34:59 +0700
committerhathach <[email protected]>2026-03-11 13:34:59 +0700
commit336e89792f9b572c5087b1df479d4e89542f6360 (patch)
tree866a0acbf5dbc952b183768f2b916ff9fe36a591 /test
parent60154a128795bcd6ca36042cac1b8bebf1a2764e (diff)
parent7249c65b2a5b995ff7c2b45c1171f218b9d71112 (diff)
Merge branch 'master' into ep0_direct
# Conflicts: # hw/bsp/same7x/boards/same70_qmtech/board.cmake # hw/bsp/same7x/boards/same70_xplained/board.cmake # hw/bsp/same7x/family.cmake
Diffstat (limited to 'test')
-rw-r--r--test/fuzz/rules.mk1
-rwxr-xr-xtest/hil/hil_test.py152
-rw-r--r--test/hil/tinyusb.json4
3 files changed, 145 insertions, 12 deletions
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 b2e883119..7cffd2da8 100755
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -151,21 +151,49 @@ def read_disk_file(uid, lun, fname):
def open_mtp_dev(uid):
mtp = MTP()
# MTP seems to take a while to enumerate
- timeout = 2*ENUM_TIMEOUT
+ 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
@@ -410,22 +438,22 @@ def test_device_cdc_dual_ports(board):
sizes = [32, 64, 128, 256, 512, random.randint(2000, 5000)]
def write_and_check(writer, payload):
- size = len(payload)
+ payload_len = len(payload)
for s in ser:
s.reset_input_buffer()
rd0 = b''
rd1 = b''
offset = 0
# Write in chunks of random 1-64 bytes (device has 64-byte buffer)
- while offset < size:
- chunk_size = min(random.randint(1, 64), size - offset)
+ while offset < payload_len:
+ chunk_size = min(random.randint(1, 64), payload_len - offset)
ser[writer].write(payload[offset:offset + chunk_size])
ser[writer].flush()
rd0 += ser[0].read(chunk_size)
rd1 += ser[1].read(chunk_size)
offset += chunk_size
- assert rd0 == payload.lower(), f'Port0 wrong data ({size}): expected {payload.lower()[:16]}... was {rd0[:16]}'
- assert rd1 == payload.upper(), f'Port1 wrong data ({size}): expected {payload.upper()[:16]}... was {rd1[:16]}'
+ assert rd0 == payload.lower(), f'Port0 wrong data ({payload_len}): expected {payload.lower()}... was {rd0}'
+ assert rd1 == payload.upper(), f'Port1 wrong data ({payload_len}): expected {payload.upper()}... was {rd1}'
for size in sizes:
payload0 = rand_ascii(size)
@@ -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 047d0879c..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"
},
@@ -107,7 +108,6 @@
"host": false,
"dual": false
},
- "comment": "MSC is slow to enumerated #2602",
"flasher": {
"name": "jlink",
"uid": "000831174392",