From a011ecf509bedb2125443b0bfc7950f5f3b057f7 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Mon, 18 Aug 2025 21:59:29 -0400 Subject: [PATCH 1/8] Add check to skip over keyboard --- Metro/Metro_RP2350_Minesweeper/code.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) mode change 100755 => 100644 Metro/Metro_RP2350_Minesweeper/code.py diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py old mode 100755 new mode 100644 index 6f3abec32..ea1100fa4 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -138,6 +138,22 @@ def update_ui(): # set the mouse configuration so it can be used mouse.set_configuration() + # Verify mouse works by reading from it + buf = array.array("b", [0] * 4) + try: + # Try to read some data with a short timeout + data = mouse.read(0x81, buf, timeout=100) + print(f"Mouse test read successful: {data} bytes") + break + except usb.core.USBTimeoutError: + # Timeout is normal if mouse isn't moving + print("Mouse connected but not sending data (normal)") + break + except Exception as e: # pylint: disable=broad-except + print(f"Mouse test read failed: {e}") + # Continue to try next device or retry + mouse = None + buf = array.array("b", [0] * 4) waiting_for_release = False left_button = right_button = False From 318448cc648e441e5368251064ca94454416ddbe Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 15:14:42 -0400 Subject: [PATCH 2/8] Use find_boot_mouse_endpoint --- Metro/Metro_RP2350_Minesweeper/code.py | 30 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index ea1100fa4..840771d33 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -13,6 +13,7 @@ from displayio import Group, OnDiskBitmap, TileGrid, Bitmap, Palette from adafruit_display_text.bitmap_label import Label from adafruit_display_text.text_box import TextBox +import adafruit_usb_host_descriptors from eventbutton import EventButton import supervisor import terminalio @@ -121,6 +122,12 @@ def update_ui(): # wait a second for USB devices to be ready time.sleep(1) +#good_devices = False +#while not good_devices: +# for device in usb.core.find(find_all=True): +# if device.manufacturer is not None: +# good_devices = True +# break # scan for connected USB devices for device in usb.core.find(find_all=True): # print information about the found devices @@ -128,12 +135,16 @@ def update_ui(): print(device.manufacturer, device.product) print(device.serial_number) + mouse_intfc,mouse_endpt = adafruit_usb_host_descriptors.find_boot_mouse_endpoint(device) + if (mouse_intfc is None or mouse_endpt is None): + continue # Not a mouse device + # assume this device is the mouse mouse = device # detach from kernel driver if active - if mouse.is_kernel_driver_active(0): - mouse.detach_kernel_driver(0) + if mouse.is_kernel_driver_active(mouse_intfc): + mouse.detach_kernel_driver(mouse_intfc) # set the mouse configuration so it can be used mouse.set_configuration() @@ -142,8 +153,13 @@ def update_ui(): buf = array.array("b", [0] * 4) try: # Try to read some data with a short timeout - data = mouse.read(0x81, buf, timeout=100) - print(f"Mouse test read successful: {data} bytes") + data = mouse.read(mouse_endpt, buf, timeout=100) + print(f"Mouse test read successful: {data} bytes - {buf}") + + # without this subsequent reads sometimes can't find the endpoint? + # I've never seen the Flush mouse queue print so it must just need the extra read + if mouse.read(mouse_endpt, buf, timeout=10) > 0: + print(f"Flush mouse queue: {buf}") break except usb.core.USBTimeoutError: # Timeout is normal if mouse isn't moving @@ -154,6 +170,10 @@ def update_ui(): # Continue to try next device or retry mouse = None +if mouse is None: + display.root_group = displayio.CIRCUITPYTHON_TERMINAL + raise RuntimeError("No mouse found. Please connect a USB mouse.") + buf = array.array("b", [0] * 4) waiting_for_release = False left_button = right_button = False @@ -271,7 +291,7 @@ def hide_group(group): try: # try to read data from the mouse, small timeout so the code will move on # quickly if there is no data - data_len = mouse.read(0x81, buf, timeout=10) + data_len = mouse.read(mouse_endpt, buf, timeout=10) left_button = buf[0] & 0x01 right_button = buf[0] & 0x02 From 59fe2fb59944f82d808869d75ad7389a335ec687 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 15:20:09 -0400 Subject: [PATCH 3/8] pylint caught this for me --- Metro/Metro_RP2350_Minesweeper/code.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index 840771d33..e193f0939 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -10,7 +10,7 @@ """ import array import time -from displayio import Group, OnDiskBitmap, TileGrid, Bitmap, Palette +from displayio import Group, OnDiskBitmap, TileGrid, Bitmap, Palette, CIRCUITPYTHON_TERMINAL from adafruit_display_text.bitmap_label import Label from adafruit_display_text.text_box import TextBox import adafruit_usb_host_descriptors @@ -171,7 +171,7 @@ def update_ui(): mouse = None if mouse is None: - display.root_group = displayio.CIRCUITPYTHON_TERMINAL + display.root_group = CIRCUITPYTHON_TERMINAL raise RuntimeError("No mouse found. Please connect a USB mouse.") buf = array.array("b", [0] * 4) From 8f89fe23c1517a5206da31182cdb22d054fc0c7e Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 16:32:30 -0400 Subject: [PATCH 4/8] ignore no endpoint failures from mouse.read --- Metro/Metro_RP2350_Minesweeper/code.py | 31 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index e193f0939..f4926c29f 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -122,12 +122,12 @@ def update_ui(): # wait a second for USB devices to be ready time.sleep(1) -#good_devices = False -#while not good_devices: -# for device in usb.core.find(find_all=True): -# if device.manufacturer is not None: -# good_devices = True -# break +good_devices = False +while not good_devices: + for device in usb.core.find(find_all=True): + if device.manufacturer is not None: + good_devices = True + break # scan for connected USB devices for device in usb.core.find(find_all=True): # print information about the found devices @@ -155,11 +155,6 @@ def update_ui(): # Try to read some data with a short timeout data = mouse.read(mouse_endpt, buf, timeout=100) print(f"Mouse test read successful: {data} bytes - {buf}") - - # without this subsequent reads sometimes can't find the endpoint? - # I've never seen the Flush mouse queue print so it must just need the extra read - if mouse.read(mouse_endpt, buf, timeout=10) > 0: - print(f"Flush mouse queue: {buf}") break except usb.core.USBTimeoutError: # Timeout is normal if mouse isn't moving @@ -291,7 +286,19 @@ def hide_group(group): try: # try to read data from the mouse, small timeout so the code will move on # quickly if there is no data - data_len = mouse.read(mouse_endpt, buf, timeout=10) + while True: + try: + # read data from the mouse endpoint + data_len = mouse.read(mouse_endpt, buf, timeout=10) + if data_len > 0: + break + except usb.core.USBTimeoutError: + # if we get a timeout error, it means there is no data available + pass + except usb.core.USBError as exc: + # if we get a USBError, it may mean the mouse is not ready yet + pass + left_button = buf[0] & 0x01 right_button = buf[0] & 0x02 From 5fbb8d9277c6698b4e63af843ceac6035ffdcae4 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 16:37:08 -0400 Subject: [PATCH 5/8] cleanup trailing spaces for pylint --- Metro/Metro_RP2350_Minesweeper/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index f4926c29f..2bb7ce555 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -291,7 +291,7 @@ def hide_group(group): # read data from the mouse endpoint data_len = mouse.read(mouse_endpt, buf, timeout=10) if data_len > 0: - break + break except usb.core.USBTimeoutError: # if we get a timeout error, it means there is no data available pass From 4fcd255f87aad600bf5ec8ebda818ee8608b7aca Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 16:51:46 -0400 Subject: [PATCH 6/8] Avoids infinite loop if no USB devices are attached --- Metro/Metro_RP2350_Minesweeper/code.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index 2bb7ce555..6d5242ab3 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -123,7 +123,8 @@ def update_ui(): time.sleep(1) good_devices = False -while not good_devices: +wait_time = time.monotonic() + 10 # wait up to 20 seconds for a good device to be found +while not good_devices and time.monotonic() < wait_time: for device in usb.core.find(find_all=True): if device.manufacturer is not None: good_devices = True From 46c942051d83f0b62c78c31950ffc4433864cf4c Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Tue, 19 Aug 2025 16:55:39 -0400 Subject: [PATCH 7/8] replace generated comment with better detail --- Metro/Metro_RP2350_Minesweeper/code.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index 6d5242ab3..32a0764ba 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -297,7 +297,7 @@ def hide_group(group): # if we get a timeout error, it means there is no data available pass except usb.core.USBError as exc: - # if we get a USBError, it may mean the mouse is not ready yet + # if we get a USBError, We may be getting no endpoint msgs which can be waited out pass left_button = buf[0] & 0x01 From 8feb030e57a15ce958272aa566da9cf910d9fac3 Mon Sep 17 00:00:00 2001 From: RetiredWizard Date: Wed, 20 Aug 2025 10:47:01 -0400 Subject: [PATCH 8/8] remove CIRCUITPYTHON_TERMINAL display before no mouse error --- Metro/Metro_RP2350_Minesweeper/code.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Metro/Metro_RP2350_Minesweeper/code.py b/Metro/Metro_RP2350_Minesweeper/code.py index 32a0764ba..4816e7e83 100644 --- a/Metro/Metro_RP2350_Minesweeper/code.py +++ b/Metro/Metro_RP2350_Minesweeper/code.py @@ -10,7 +10,7 @@ """ import array import time -from displayio import Group, OnDiskBitmap, TileGrid, Bitmap, Palette, CIRCUITPYTHON_TERMINAL +from displayio import Group, OnDiskBitmap, TileGrid, Bitmap, Palette from adafruit_display_text.bitmap_label import Label from adafruit_display_text.text_box import TextBox import adafruit_usb_host_descriptors @@ -167,7 +167,6 @@ def update_ui(): mouse = None if mouse is None: - display.root_group = CIRCUITPYTHON_TERMINAL raise RuntimeError("No mouse found. Please connect a USB mouse.") buf = array.array("b", [0] * 4)