From b8d1acd1049d0535c9c2ef8f63a7aea82abd9cbd Mon Sep 17 00:00:00 2001
From: hathach <thach@tinyusb.org>
Date: Wed, 29 Nov 2023 12:00:52 +0700
Subject: [PATCH] improve hil test, correct pi4 uuid

---
 test/hil/hil_pi4.json            |   4 +-
 test/hil/hil_test.py             | 123 +++++++++++++++++--------------
 tools/codespell/ignore-words.txt |   1 +
 3 files changed, 69 insertions(+), 59 deletions(-)

diff --git a/test/hil/hil_pi4.json b/test/hil/hil_pi4.json
index 18ac12bc4..d613f8da8 100644
--- a/test/hil/hil_pi4.json
+++ b/test/hil/hil_pi4.json
@@ -2,9 +2,9 @@
     "boards": [
         {
             "name": "raspberry_pi_pico",
-            "uid": "E6614103E72C1D2F",
+            "uid": "E6614C311B764A37",
             "debugger": "openocd",
-            "debugger_sn": "E6614C311B764A37",
+            "debugger_sn": "E6614103E72C1D2F",
             "debugger_args": "-f interface/cmsis-dap.cfg -f target/rp2040.cfg -c \"adapter speed 5000\""
         }
     ]
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index a6542fe2d..5f8425549 100644
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -32,22 +32,66 @@ import serial
 import subprocess
 import json
 
+ENUM_TIMEOUT = 10
 
-def get_serial_dev(id, product, ifnum):
+
+def get_serial_dev(id, vendor_str, product_str, ifnum):
     # get usb serial by id
-    return f'/dev/serial/by-id/usb-TinyUSB_{product}_{id}-if{ifnum:02d}'
+    return f'/dev/serial/by-id/usb-{vendor_str}_{product_str}_{id}-if{ifnum:02d}'
 
 
 # Currently not used, left as reference
-def get_disk_dev(id, lun):
+def get_disk_dev(id, vendor_str, lun):
     # get usb disk by id
-    return f'/dev/disk/by-id/usb-TinyUSB_Mass_Storage_{id}-0:{lun}'
+    return f'/dev/disk/by-id/usb-{vendor_str}_Mass_Storage_{id}-0:{lun}'
 
 
-def get_hid_dev(id, product, event):
-    return f'/dev/input/by-id/usb-TinyUSB_{product}_{id}-{event}'
+def get_hid_dev(id, vendor_str, product_str, event):
+    return f'/dev/input/by-id/usb-{vendor_str}_{product_str}_{id}-{event}'
 
 
+def open_serial_dev(port):
+    timeout = ENUM_TIMEOUT
+    ser = None
+    while timeout:
+        if os.path.exists(port):
+            try:
+                # slight delay since kernel may occupy the port briefly
+                time.sleep(0.2)
+                ser = serial.Serial(port, timeout=1)
+                break
+            except serial.SerialException:
+                pass
+        time.sleep(0.8)
+        timeout = timeout - 1
+    assert timeout, 'Device not available or Cannot open port'
+    return ser
+
+
+def read_disk_file(id, fname):
+    # on different self-hosted, the mount point is different
+    file_list = [
+        f'/media/blkUSB_{id[-8:]}.02/{fname}',
+        f'/media/{os.getenv("USER")}/TinyUSB MSC/{fname}'
+    ]
+    timeout = ENUM_TIMEOUT
+    while timeout:
+        for file in file_list:
+            if os.path.isfile(file):
+                with open(file, 'rb') as f:
+                    data = f.read()
+                    return data
+
+        time.sleep(1)
+        timeout = timeout - 1
+
+    assert timeout, 'Device not available'
+    return None
+
+
+# -------------------------------------------------------------
+# Flash with debugger
+# -------------------------------------------------------------
 def flash_jlink(sn, dev, firmware):
     script = ['halt', 'r', f'loadfile {firmware}', 'r', 'go', 'exit']
     f = open('flash.jlink', 'w')
@@ -61,7 +105,6 @@ def flash_jlink(sn, dev, firmware):
 
 
 def flash_openocd(sn, args, firmware):
-
     ret = subprocess.run(f'openocd {args} -c "program {firmware} reset exit"',
                          shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     stdout = ret.stdout.decode()
@@ -77,26 +120,13 @@ def test_board_test(id):
 
 
 def test_cdc_dual_ports(id):
-    port1 = get_serial_dev(id, "TinyUSB_Device", 0)
-    port2 = get_serial_dev(id, "TinyUSB_Device", 2)
+    port1 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0)
+    port2 = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 2)
 
-    # Wait device enum
-    timeout = 10
-    while timeout:
-        if os.path.exists(port1) and os.path.exists(port2):
-            break
-        time.sleep(1)
-        timeout = timeout - 1
-
-    assert timeout, 'Device not available'
+    ser1 = open_serial_dev(port1)
+    ser2 = open_serial_dev(port2)
 
     # Echo test
-    ser1 = serial.Serial(port1)
-    ser2 = serial.Serial(port2)
-
-    ser1.timeout = 1
-    ser2.timeout = 1
-
     str1 = b"test_no1"
     ser1.write(str1)
     ser1.flush()
@@ -111,38 +141,17 @@ def test_cdc_dual_ports(id):
 
 
 def test_cdc_msc(id):
-    port = get_serial_dev(id, "TinyUSB_Device", 0)
-    file_list = [f'/media/blkUSB_{id[-8:]}.02/README.TXT', f'/media/{os.getenv("USER")}/TinyUSB MSC/README.TXT']
-    # Wait device enum
-    timeout = 10
-    while timeout:
-        f_found = False
-        if os.path.exists(port):
-            for file in file_list:
-                if os.path.isfile(file):
-                    f_found = True
-                    f = open(file, 'rb')
-                    data = f.read()
-                    break
-
-        if f_found:
-            break
-
-        time.sleep(1)
-        timeout = timeout - 1
-
-    assert timeout, 'Device not available'
-
     # Echo test
-    ser1 = serial.Serial(port)
-    ser1.timeout = 1
+    port = get_serial_dev(id, 'TinyUSB', "TinyUSB_Device", 0)
+    ser = open_serial_dev(port)
 
     str = b"test_str"
-    ser1.write(str)
-    ser1.flush()
-    assert ser1.read(100) == str, 'CDC wrong data'
+    ser.write(str)
+    ser.flush()
+    assert ser.read(100) == str, 'CDC wrong data'
 
     # Block test
+    data = read_disk_file(id, 'README.TXT')
     readme = \
     b"This is tinyusb's MassStorage Class demo.\r\n\r\n\
 If you find any bugs or get any questions, feel free to file an\r\n\
@@ -153,7 +162,7 @@ issue at github.com/hathach/tinyusb"
 
 def test_dfu(id):
     # Wait device enum
-    timeout = 10
+    timeout = ENUM_TIMEOUT
     while timeout:
         ret = subprocess.run(f'dfu-util -l',
                          shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
@@ -192,7 +201,7 @@ def test_dfu(id):
 
 def test_dfu_runtime(id):
     # Wait device enum
-    timeout = 10
+    timeout = ENUM_TIMEOUT
     while timeout:
         ret = subprocess.run(f'dfu-util -l',
                          shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
@@ -206,11 +215,11 @@ def test_dfu_runtime(id):
 
 
 def test_hid_boot_interface(id):
-    kbd = get_hid_dev(id, 'TinyUSB_Device', 'event-kbd')
-    mouse1 = get_hid_dev(id, 'TinyUSB_Device', 'if01-event-mouse')
-    mouse2 = get_hid_dev(id, 'TinyUSB_Device', 'if01-mouse')
+    kbd = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'event-kbd')
+    mouse1 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-event-mouse')
+    mouse2 = get_hid_dev(id, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse')
     # Wait device enum
-    timeout = 10
+    timeout = ENUM_TIMEOUT
     while timeout:
         if os.path.exists(kbd) and os.path.exists(mouse1) and os.path.exists(mouse2):
             break
diff --git a/tools/codespell/ignore-words.txt b/tools/codespell/ignore-words.txt
index 2513691cb..957cbd86b 100644
--- a/tools/codespell/ignore-words.txt
+++ b/tools/codespell/ignore-words.txt
@@ -11,3 +11,4 @@ attch
 endianess
 pris
 busses
+ser