33# MIT license; Copyright (c) 2023-2024 Angus Gratton
44from micropython import const
55import struct
6+ import machine
67
78from usb.device.hid import HIDInterface
89
@@ -20,6 +21,7 @@ def __init__(self, interface_str="MicroPython Mouse"):
2021 self._l = False # Left button
2122 self._m = False # Middle button
2223 self._r = False # Right button
24+ self._buf = bytearray(3)
2325
2426 def send_report(self, dx=0, dy=0):
2527 b = 0
@@ -29,16 +31,20 @@ def send_report(self, dx=0, dy=0):
2931 b |= 1 << 1
3032 if self._m:
3133 b |= 1 << 2
32- # Note: This allocates the bytes object 'report' each time a report is
33- # sent.
34+
35+ # Wait for any pending report to be sent to the host
36+ # before updating contents of _buf.
3437 #
35- # However, at the moment the HIDInterface class doesn't keep track of each
36- # transfer after it's submitted. So reusing a bytearray() creates a risk
37- # of a race condition if a new report transfer is submitted using the
38- # same buffer, before the previous one has completed.
39- report = struct.pack("Bbb", b, dx, dy)
38+ # This loop can be removed if you don't care about possibly missing a
39+ # transient report, the final report buffer contents will always be the
40+ # last one sent to the host (it just might lose one of the ones in the
41+ # middle).
42+ while self.busy():
43+ machine.idle()
44+
45+ struct.pack_into("Bbb", self._buf, 0, b, dx, dy)
4046
41- return super().send_report(report )
47+ return super().send_report(self._buf )
4248
4349 def click_left(self, down=True):
4450 self._l = down
0 commit comments