diff options
| author | hathach <[email protected]> | 2026-03-11 13:34:59 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-03-11 13:34:59 +0700 |
| commit | 336e89792f9b572c5087b1df479d4e89542f6360 (patch) | |
| tree | 866a0acbf5dbc952b183768f2b916ff9fe36a591 /test | |
| parent | 60154a128795bcd6ca36042cac1b8bebf1a2764e (diff) | |
| parent | 7249c65b2a5b995ff7c2b45c1171f218b9d71112 (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.mk | 1 | ||||
| -rwxr-xr-x | test/hil/hil_test.py | 152 | ||||
| -rw-r--r-- | test/hil/tinyusb.json | 4 |
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", |
