Skip to content

wait for HID device ready; allow longer mouse movements #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions adafruit_hid/consumer_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* Author(s): Dan Halbert
"""

import time
import usb_hid

class ConsumerControl:
Expand All @@ -52,6 +53,14 @@ def __init__(self):
# View bytes as a single 16-bit number.
self.usage_id = memoryview(self.report)[0:2]

# Do a no-op to test if HID device is ready.
# If not, wait a bit and try once more.
try:
self.send(0x0)
except OSError:
time.sleep(1)
self.send(0x0)
Copy link
Collaborator

@sommersoft sommersoft Apr 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a nested try, so we can at raise the exception and report it if the wait->retry doesn't work?

And to extend that, is there an actual error number we can attribute this too? Could be useful so that we don't treat ALL OSErrors as needing to wait (unless we're confident that is the only one that will be encountered).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second self.send() will throw OSError if it fails, just like the first. But that won't get caught so it will bubble up to the user.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the error number will be the same across all ports, or even from 2.x to 3.0. There are a couple of different conditions that are reported up that might be recoverable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was afraid we couldn't narrow down on the error number; cest la vie. For the exception, I was just wondering if there was a better way to report than the status LED. But, since we're dealing with situations very early in the program running, REPL output is unlikely. And clearly, if the REPL is running, HID is probably fully initialized. Only other way around it is to have the user put their instance creation in a try and catch any exception themselves...

This looks good to me as is then. I'll let @tannewt review and final approve.


def send(self, consumer_code):
"""Send a report to do the specified consumer control action,
and then stop the action (so it will not repeat).
Expand Down
13 changes: 12 additions & 1 deletion adafruit_hid/keyboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
* Author(s): Scott Shawcroft, Dan Halbert
"""

from micropython import const
import time
import usb_hid

from micropython import const

from .keycode import Keycode

class Keyboard:
Expand Down Expand Up @@ -63,6 +65,15 @@ def __init__(self):
# View onto bytes 2-7 in report.
self.report_keys = memoryview(self.report)[2:]

# Do a no-op to test if HID device is ready.
# If not, wait a bit and try once more.
try:
self.release_all()
except OSError:
time.sleep(1)
self.release_all()


def press(self, *keycodes):
"""Send a report indicating that the given keys have been pressed.

Expand Down
34 changes: 22 additions & 12 deletions adafruit_hid/mouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

* Author(s): Dan Halbert
"""
import time
import usb_hid

class Mouse:
Expand Down Expand Up @@ -56,6 +57,13 @@ def __init__(self):
# report[3] wheel movement
self.report = bytearray(4)

# Do a no-op to test if HID device is ready.
# If not, wait a bit and try once more.
try:
self.move(0, 0, 0)
except OSError:
time.sleep(1)
self.move(0, 0, 0)

def press(self, buttons):
"""Press the given mouse buttons.
Expand Down Expand Up @@ -116,7 +124,6 @@ def move(self, x=0, y=0, wheel=0):
positive is downwards.
:param wheel: Rotate the wheel this amount. Negative is toward the user, positive
is away from the user. The scrolling effect depends on the host.
:raises ValueError: if any argument is not in the range -127 to 127 inclusive.

Examples::

Expand All @@ -133,17 +140,20 @@ def move(self, x=0, y=0, wheel=0):
# Roll the mouse wheel away from the user.
m.move(wheel=1)
"""
if (self._distance_ok(x)
and self._distance_ok(y)
and self._distance_ok(wheel)):
self.report[1] = x
self.report[2] = y
self.report[3] = wheel

# Send multiple reports if necessary to move or scroll requested amounts.
while x != 0 or y != 0 or wheel != 0:
partial_x = self._limit(x)
partial_y = self._limit(y)
partial_wheel = self._limit(wheel)
self.report[1] = partial_x
self.report[2] = partial_y
self.report[3] = partial_wheel
self.hid_mouse.send_report(self.report)
else:
raise ValueError('All arguments must be >= -127 and <= 127')
x -= partial_x
y -= partial_y
wheel -= partial_wheel

@staticmethod
def _distance_ok(dist):
"""Return True if dist is in the range [-127,127]"""
return -127 <= dist <= 127
def _limit(dist):
return min(127, max(-127, dist))