Skip to content

Commit 5ad0efa

Browse files
committed
use adafruit_usb_host_mouse
1 parent 5ac9e6c commit 5ad0efa

File tree

1 file changed

+33
-164
lines changed

1 file changed

+33
-164
lines changed

Fruit_Jam/Fruit_Jam_PyPaint/code.py

Lines changed: 33 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import displayio
2525

2626
try:
27-
import usb.core
27+
from adafruit_usb_host_mouse import find_and_init_boot_mouse
2828
usb_available = True
2929
except ImportError:
3030
usb_available = False
@@ -206,111 +206,12 @@ def __init__(self, splash, cursor_bmp, screen_width, screen_height):
206206

207207

208208
def find_mouse(self): # pylint: disable=too-many-statements, too-many-locals
209-
"""Find the mouse device with multiple retry attempts"""
210-
MAX_ATTEMPTS = 5
211-
RETRY_DELAY = 1 # seconds
212-
213-
if not usb_available:
214-
print("USB library not available; cannot find mouse.")
209+
"""Find and initialize the USB mouse."""
210+
self.mouse = find_and_init_boot_mouse()
211+
if self.mouse is None:
212+
print("No mouse found.")
215213
return False
216-
217-
for attempt in range(MAX_ATTEMPTS):
218-
print(f"Mouse detection attempt {attempt+1}/{MAX_ATTEMPTS}")
219-
220-
# Constants for USB control transfers
221-
DIR_OUT = 0
222-
# DIR_IN = 0x80 # Unused variable
223-
REQTYPE_CLASS = 1 << 5
224-
REQREC_INTERFACE = 1 << 0
225-
HID_REQ_SET_PROTOCOL = 0x0B
226-
227-
# Find all USB devices
228-
devices_found = False
229-
230-
for device in usb.core.find(find_all=True):
231-
devices_found = True
232-
print(f"Found device: {device.idVendor:04x}:{device.idProduct:04x}")
233-
234-
try:
235-
# Try to get device info
236-
try:
237-
manufacturer = device.manufacturer
238-
product = device.product
239-
except Exception: # pylint: disable=broad-except
240-
manufacturer = "Unknown"
241-
product = "Unknown"
242-
243-
# Just use whatever device we find
244-
self.mouse = device
245-
246-
# Try to detach kernel driver
247-
try:
248-
has_kernel_driver = hasattr(device, 'is_kernel_driver_active')
249-
if has_kernel_driver and device.is_kernel_driver_active(0):
250-
device.detach_kernel_driver(0)
251-
except Exception as e: # pylint: disable=broad-except
252-
print(f"Error detaching kernel driver: {e}")
253-
254-
# Set configuration
255-
try:
256-
device.set_configuration()
257-
except Exception as e: # pylint: disable=broad-except
258-
print(f"Error setting configuration: {e}")
259-
continue # Try next device
260-
261-
# Just assume endpoint 0x81 (common for mice)
262-
self.in_endpoint = 0x81
263-
print(f"Using mouse: {manufacturer}, {product}")
264-
265-
# Set to report protocol mode
266-
try:
267-
bmRequestType = DIR_OUT | REQTYPE_CLASS | REQREC_INTERFACE
268-
bRequest = HID_REQ_SET_PROTOCOL
269-
wValue = 1 # 1 = report protocol
270-
wIndex = 0 # First interface
271-
272-
buf = bytearray(1)
273-
device.ctrl_transfer(bmRequestType, bRequest, wValue, wIndex, buf)
274-
print("Set to report protocol mode")
275-
except Exception as e: # pylint: disable=broad-except
276-
print(f"Could not set protocol: {e}")
277-
278-
# Buffer for reading data
279-
self.buf = array.array("B", [0] * 4)
280-
print("Created 4-byte buffer for mouse data")
281-
282-
# Verify mouse works by reading from it
283-
try:
284-
# Try to read some data with a short timeout
285-
data = device.read(self.in_endpoint, self.buf, timeout=100)
286-
print(f"Mouse test read successful: {data} bytes")
287-
return True
288-
except usb.core.USBTimeoutError:
289-
# Timeout is normal if mouse isn't moving
290-
print("Mouse connected but not sending data (normal)")
291-
return True
292-
except Exception as e: # pylint: disable=broad-except
293-
print(f"Mouse test read failed: {e}")
294-
# Continue to try next device or retry
295-
self.mouse = None
296-
self.in_endpoint = None
297-
continue
298-
299-
except Exception as e: # pylint: disable=broad-except
300-
print(f"Error initializing device: {e}")
301-
continue
302-
303-
if not devices_found:
304-
print("No USB devices found")
305-
306-
# If we get here without returning, no suitable mouse was found
307-
print(f"No working mouse found on attempt {attempt+1}, retrying...")
308-
gc.collect()
309-
time.sleep(RETRY_DELAY)
310-
311-
print("Failed to find a working mouse after multiple attempts")
312-
return False
313-
214+
return True
314215

315216
def poll(self):
316217
"""Check for input. Returns contact (a bool), False (no button B),
@@ -345,72 +246,40 @@ def set_cursor_bitmap(self, bmp):
345246
def _process_mouse_input(self):
346247
"""Process mouse input - simplified version without wheel support"""
347248

348-
try:
349-
# Attempt to read data from the mouse (10ms timeout)
350-
count = self.mouse.read(self.in_endpoint, self.buf, timeout=10)
351-
352-
except usb.core.USBTimeoutError:
353-
# Timeout is normal if mouse isn't moving
354-
return False
355-
except usb.core.USBError as e:
356-
# Handle timeouts silently
357-
if e.errno == 110: # Operation timed out
358-
return False
359-
360-
# Handle disconnections
361-
if e.errno == 19: # No such device
362-
print("Mouse disconnected")
363-
self.mouse = None
364-
self.in_endpoint = None
365-
gc.collect()
366-
367-
return False
368-
except Exception as e: # pylint: disable=broad-except
369-
print(f"Error reading mouse: {type(e).__name__}")
370-
return False
371-
372-
if count >= 3: # We need at least buttons, X and Y
373-
# Extract mouse button states
374-
buttons = self.buf[0]
375-
x = self.buf[1]
376-
y = self.buf[2]
377-
378-
# Convert to signed values if needed
379-
if x > 127:
380-
x = x - 256
381-
if y > 127:
382-
y = y - 256
249+
buttons = self.mouse.update()
383250

384-
# Extract button states
385-
current_left_button_state = buttons & 0x01
386-
current_right_button_state = (buttons & 0x02) >> 1
387-
388-
# Detect button presses
389-
if current_left_button_state == 1 and self.last_left_button_state == 0:
390-
self.left_button_pressed = True
391-
elif current_left_button_state == 0 and self.last_left_button_state == 1:
392-
self.left_button_pressed = False
251+
# Extract button states
252+
if buttons is None:
253+
current_left_button_state = 0
254+
current_right_button_state = 0
255+
else:
256+
current_left_button_state = 1 if 'left' in buttons else 0
257+
current_right_button_state = 1 if 'right' in buttons else 0
393258

394-
if current_right_button_state == 1 and self.last_right_button_state == 0:
395-
self.right_button_pressed = True
396-
elif current_right_button_state == 0 and self.last_right_button_state == 1:
397-
self.right_button_pressed = False
259+
# Detect button presses
260+
if current_left_button_state == 1 and self.last_left_button_state == 0:
261+
self.left_button_pressed = True
262+
elif current_left_button_state == 0 and self.last_left_button_state == 1:
263+
self.left_button_pressed = False
398264

399-
# Update button states
400-
self.last_left_button_state = current_left_button_state
401-
self.last_right_button_state = current_right_button_state
265+
if current_right_button_state == 1 and self.last_right_button_state == 0:
266+
self.right_button_pressed = True
267+
elif current_right_button_state == 0 and self.last_right_button_state == 1:
268+
self.right_button_pressed = False
402269

403-
# Update position
404-
self.mouse_x += x
405-
self.mouse_y += y
270+
# Update button states
271+
self.last_left_button_state = current_left_button_state
272+
self.last_right_button_state = current_right_button_state
406273

407-
# Ensure position stays within bounds
408-
self.mouse_x = max(0, min(self.SCREEN_WIDTH - 1, self.mouse_x))
409-
self.mouse_y = max(0, min(self.SCREEN_HEIGHT - 1, self.mouse_y))
274+
# Update position
275+
self.mouse_x = self.mouse.x
276+
self.mouse_y = self.mouse.y
410277

411-
return True
278+
# Ensure position stays within bounds
279+
self.mouse_x = max(0, min(self.SCREEN_WIDTH - 1, self.mouse_x))
280+
self.mouse_y = max(0, min(self.SCREEN_HEIGHT - 1, self.mouse_y))
412281

413-
return False
282+
return True
414283

415284
################################################################################
416285

0 commit comments

Comments
 (0)