Skip to content

Add Keyboard class with API to send HID reports; prune constants; change examples #1

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 8 commits into from
Apr 12, 2017
Merged
Show file tree
Hide file tree
Changes from 7 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
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
__pycache__
_build
*.pyc
__pycache__
_build
*.pyc
.vscode
108 changes: 76 additions & 32 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Introduction
:target: https://gitter.im/adafruit/circuitpython?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
:alt: Gitter

This driver provides USB HID related constants. In the future it will include
helper functions and classes as well.
This driver simulates USB HID devices, such as keyboard, mouse, and joystick.

Currently keyboard and mouse are implemented.

Dependencies
=============
Expand All @@ -26,39 +27,82 @@ This is easily achieved by downloading
Usage Example
=============

The current `keyboard` module stores key constants which make it easier to
construct keypress reports for a keyboard device.
The ``Keyboard`` class sends keypress reports for a USB keyboard device to the host.

The ``Keycode`` class defines USB HID keycodes to send using ``Keyboard``.

.. code-block:: python

import usb_hid
import adafruit_hid.keyboard as kbd
import time

report = bytearray(8) # Keyboard reports are always 8 bytes.

# Devices are initialized earlier so find the one for the keyboard.
keyboard = None
for device in usb_hid.devices:
if device.usage_page is 0x1 and device.usage is 0x06:
keyboard = device
break

# The first byte of the report includes a bitfield indicating which
# modifiers are pressed. Their bit position is their code's difference from
# 0xE0.
report[0] |= 1 << (kbd.LEFT_SHIFT - 0xE0)
# Normal keys are simply their byte code in bytes 2-7. When fewer than six
# keys are pressed then the trailing bytes are zero.
report[2] = kbd.A
keyboard.send_report(report)

time.sleep(0.1)

# Clear the key presses and send another report.
report[0] = 0
report[2] = 0
keyboard.send_report(report)
from adafruit_hid import Keyboard
from adafruit_hid import Keycode

# Set up a keyboard device.
kbd = Keyboard()

# Type control-x.
kbd.press(Keycode.CONTROL, Keycode.X)
kbd.release_all()

# Type capital 'A'.
kbd.press(Keycode.SHIFT, Keycode.A)
kbd.release_all()

# Press and hold the shifted '1' key to get '!' (exclamation mark).
kbd.press(Keycode.SHIFT, Keycode.ONE)
# Release the ONE key and send another report.
kbd.release(Keycode.ONE)
# Press shifted '2' to get '@'.
kbd.press(Keycode.TWO)
# Release all keys.
kbd.release_all()

The ``USKeyboardLayout`` sends ASCII characters using keypresses. It assumes
the host is set to accept keypresses from a US keyboard.

If the host is expecting a non-US keyboard, the character to key mapping provided by
``USKeyboardLayout`` will not always be correct.
Different keypresses will be needed in some cases. For instance, to type an ``'A'`` on
a French keyboard (AZERTY instead of QWERTY), ``Keycode.Q`` should be pressed.

Currently this package provides only ``USKeyboardLayout``. More ``KeyboardLayout``
classes could be added to handle non-US keyboards and the different input methods provided
by various operating systems.

.. code-block:: python

from adafruit_hid import Keyboard
from adafruit_hid import USKeyboardLayout

kbd = Keyboard()
layout = USKeyboardLayout(kbd)

# Type 'abc' followed by Enter (a newline).
layout.write('abc\n')

# Get the keycodes needed to type a '$'.
# The method will return (Keycode.SHIFT, Keycode.FOUR).
keycodes = layout.keycodes('$')

The ``Mouse` class simulates a three-button mouse with a scroll wheel.
Copy link
Member

Choose a reason for hiding this comment

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

missing a ` after Mouse


.. code-block:: python

from adafruit_hid import Mouse

m = Mouse()

# Click the left mouse button.
m.click(Mouse.LEFT_BUTTON)

# Move the mouse diagonally to the upper left.
m.move(-100, 100, 0)

# Move the mouse while holding down the left button.
m.press(Mouse.LEFT_BUTTON)
m.move(50, 20, 0)
m.release_all() # or m.release(Mouse.LEFT_BUTTON)



Contributing
============
Expand Down
11 changes: 10 additions & 1 deletion adafruit_hid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,14 @@

TODO(description)

* Author(s): Scott Shawcroft
* Author(s): Scott Shawcroft, Dan Halbert
"""
# Import these for convenience so that the user may import the packages classes
# directly without needing to know the file names.
# E.g.:
# from adafruit_hid import Keyboard

from .keyboard import Keyboard
from .keycode import Keycode
from .mouse import Mouse
from .us_keyboard_layout import USKeyboardLayout
Copy link
Member

Choose a reason for hiding this comment

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

Please remove these. It forces all adafruit_hid loads to load all of the submodules.

With these imports:

Adafruit CircuitPython 0.9.3-1-g48107220-dirty on 2017-04-07; Adafruit Feather M0 Express with samd21g18
>>> import gc
>>> gc.collect()
>>> gc.mem_free()
15632
>>> from adafruit_hid.keycode import Keycode
>gc.collect()
>>> gc.mem_free()
6464
>>> from adafruit_hid.mouse import Mouse
>>> gc.collect()
>>> gc.mem_free()
6432

After removing them:

Adafruit CircuitPython 0.9.3-1-g48107220-dirty on 2017-04-07; Adafruit Feather M0 Express with samd21g18
>>> import gc
>>> gc.collect()
>>> gc.mem_free()
15584
>>> from adafruit_hid.mouse import Mouse
>>> gc.collect()
>>> gc.mem_free()
13856
>>> from adafruit_hid.keycode import Keycode
>>> gc.collect()
>>> gc.mem_free()
10368

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oops, yes. I forgot it would parse the whole thing.

Loading