aboutsummaryrefslogtreecommitdiff
path: root/circuitpython/frozen/Adafruit_CircuitPython_HID
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2022-06-19 19:47:51 +0530
commit4fd287655a72b9aea14cdac715ad5b90ed082ed2 (patch)
tree65d393bc0e699dd12d05b29ba568e04cea666207 /circuitpython/frozen/Adafruit_CircuitPython_HID
parent0150f70ce9c39e9e6dd878766c0620c85e47bed0 (diff)
add circuitpython code
Diffstat (limited to 'circuitpython/frozen/Adafruit_CircuitPython_HID')
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/.pre-commit-config.yaml42
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/.pylintrc436
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/.readthedocs.yaml15
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/CODE_OF_CONDUCT.md135
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSE21
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/CC-BY-4.0.txt324
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/MIT.txt19
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/Unlicense.txt20
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst160
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst.license3
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/__init__.py45
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control.py106
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control_code.py47
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard.py189
-rwxr-xr-xcircuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_base.py186
-rwxr-xr-xcircuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_us.py166
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keycode.py312
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/mouse.py152
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.icobin0 -> 4414 bytes
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico.license3
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst23
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst.license3
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/conf.py176
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst44
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst.license3
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst45
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst.license3
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/docs/requirements.txt5
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_consumer_control_brightness.py32
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_gamepad.py157
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_joywing_gamepad.py76
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_keyboard_shortcuts.py32
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simple_gamepad.py57
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simpletest.py31
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/requirements.txt5
-rw-r--r--circuitpython/frozen/Adafruit_CircuitPython_HID/setup.py55
36 files changed, 3128 insertions, 0 deletions
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/.pre-commit-config.yaml b/circuitpython/frozen/Adafruit_CircuitPython_HID/.pre-commit-config.yaml
new file mode 100644
index 0000000..43d1385
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/.pre-commit-config.yaml
@@ -0,0 +1,42 @@
+# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
+#
+# SPDX-License-Identifier: Unlicense
+
+repos:
+- repo: https://github.com/python/black
+ rev: 20.8b1
+ hooks:
+ - id: black
+- repo: https://github.com/fsfe/reuse-tool
+ rev: v0.12.1
+ hooks:
+ - id: reuse
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v2.3.0
+ hooks:
+ - id: check-yaml
+ - id: end-of-file-fixer
+ - id: trailing-whitespace
+- repo: https://github.com/pycqa/pylint
+ rev: v2.11.1
+ hooks:
+ - id: pylint
+ name: pylint (library code)
+ types: [python]
+ args:
+ - --disable=consider-using-f-string,duplicate-code
+ exclude: "^(docs/|examples/|tests/|setup.py$)"
+ - id: pylint
+ name: pylint (example code)
+ description: Run pylint rules on "examples/*.py" files
+ types: [python]
+ files: "^examples/"
+ args:
+ - --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code
+ - id: pylint
+ name: pylint (test code)
+ description: Run pylint rules on "tests/*.py" files
+ types: [python]
+ files: "^tests/"
+ args:
+ - --disable=missing-docstring,consider-using-f-string,duplicate-code
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/.pylintrc b/circuitpython/frozen/Adafruit_CircuitPython_HID/.pylintrc
new file mode 100644
index 0000000..cfd1c41
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/.pylintrc
@@ -0,0 +1,436 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: Unlicense
+
+[MASTER]
+
+# A comma-separated list of package or module names from where C extensions may
+# be loaded. Extensions are loading into the active Python interpreter and may
+# run arbitrary code
+extension-pkg-whitelist=
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Add files or directories matching the regex patterns to the blacklist. The
+# regex matches against base names, not paths.
+ignore-patterns=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Use multiple processes to speed up Pylint.
+jobs=1
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# Specify a configuration file.
+#rcfile=
+
+# Allow loading of arbitrary C extensions. Extensions are imported into the
+# active Python interpreter and may run arbitrary code.
+unsafe-load-any-extension=no
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
+confidence=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once).You can also use "--disable=all" to
+# disable everything first and then reenable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use"--disable=all --enable=classes
+# --disable=W"
+# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
+disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation,unspecified-encoding
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=
+
+
+[REPORTS]
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details
+#msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio).You can also give a reporter class, eg
+# mypackage.mymodule.MyReporterClass.
+output-format=text
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+
+[LOGGING]
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format
+logging-modules=logging
+
+
+[SPELLING]
+
+# Spelling dictionary name. Available dictionaries: none. To make it working
+# install python-enchant package.
+spelling-dict=
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to indicated private dictionary in
+# --spelling-private-dict-file option instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+# notes=FIXME,XXX,TODO
+notes=FIXME,XXX
+
+
+[TYPECHECK]
+
+# List of decorators that produce context managers, such as
+# contextlib.contextmanager. Add to this list to register other decorators that
+# produce valid context managers.
+contextmanager-decorators=contextlib.contextmanager
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E1101 when accessed. Python regular
+# expressions are accepted.
+generated-members=
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# This flag controls whether pylint should warn about no-member and similar
+# checks whenever an opaque object is returned when inferring. The inference
+# can return multiple potential results while evaluating a Python object, but
+# some branches might not be evaluated, which results in partial inference. In
+# that case, it might be useful to still emit no-member and other checks for
+# the rest of the inferred objects.
+ignore-on-opaque-inference=yes
+
+# List of class names for which member attributes should not be checked (useful
+# for classes with dynamically set attributes). This supports the use of
+# qualified names.
+ignored-classes=optparse.Values,thread._local,_thread._local
+
+# List of module names for which member attributes should not be checked
+# (useful for modules/projects where namespaces are manipulated during runtime
+# and thus existing member attributes cannot be deduced by static analysis. It
+# supports qualified module names, as well as Unix pattern matching.
+ignored-modules=board
+
+# Show a hint with possible names when a member name was not found. The aspect
+# of finding the hint is based on edit distance.
+missing-member-hint=yes
+
+# The minimum edit distance a name should have in order to be considered a
+# similar match for a missing member name.
+missing-member-hint-distance=1
+
+# The total number of similar names that should be taken in consideration when
+# showing a hint for a missing member.
+missing-member-max-choices=1
+
+
+[VARIABLES]
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,_cb
+
+# A regular expression matching the name of dummy variables (i.e. expectedly
+# not used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,future.builtins
+
+
+[FORMAT]
+
+# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
+# expected-line-ending-format=
+expected-line-ending-format=LF
+
+# Regexp for a line that is allowed to be longer than the limit.
+ignore-long-lines=^\s*(# )?<?https?://\S+>?$
+
+# Number of spaces of indent required inside a hanging or continued line.
+indent-after-paren=4
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string=' '
+
+# Maximum number of characters on a single line.
+max-line-length=100
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# List of optional constructs for which whitespace checking is disabled. `dict-
+# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
+# `trailing-comma` allows a space between comma and closing bracket: (a, ).
+# `empty-line` allows space-only lines.
+no-space-check=trailing-comma,dict-separator
+
+# Allow the body of a class to be on the same line as the declaration if body
+# contains single statement.
+single-line-class-stmt=no
+
+# Allow the body of an if to be on the same line as the test if there is no
+# else.
+single-line-if-stmt=no
+
+
+[SIMILARITIES]
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+# Ignore imports when computing similarities.
+ignore-imports=yes
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[BASIC]
+
+# Naming hint for argument names
+argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct argument names
+argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Naming hint for attribute names
+attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct attribute names
+attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Naming hint for class attribute names
+class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Regular expression matching correct class attribute names
+class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
+
+# Naming hint for class names
+# class-name-hint=[A-Z_][a-zA-Z0-9]+$
+class-name-hint=[A-Z_][a-zA-Z0-9_]+$
+
+# Regular expression matching correct class names
+# class-rgx=[A-Z_][a-zA-Z0-9]+$
+class-rgx=[A-Z_][a-zA-Z0-9_]+$
+
+# Naming hint for constant names
+const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression matching correct constant names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Minimum line length for functions/classes that require docstrings, shorter
+# ones are exempt.
+docstring-min-length=-1
+
+# Naming hint for function names
+function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct function names
+function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Good variable names which should always be accepted, separated by a comma
+# good-names=i,j,k,ex,Run,_
+good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
+
+# Include a hint for the correct naming format with invalid-name
+include-naming-hint=no
+
+# Naming hint for inline iteration names
+inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+
+# Regular expression matching correct inline iteration names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Naming hint for method names
+method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct method names
+method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Naming hint for module names
+module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression matching correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Colon-delimited sets of names that determine each other's naming style when
+# the name regexes allow several styles.
+name-group=
+
+# Regular expression which should only match function or class names that do
+# not require a docstring.
+no-docstring-rgx=^_
+
+# List of decorators that produce properties, such as abc.abstractproperty. Add
+# to this list to register other decorators that produce valid properties.
+property-classes=abc.abstractproperty
+
+# Naming hint for variable names
+variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+# Regular expression matching correct variable names
+variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+
+
+[IMPORTS]
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Analyse import fallback blocks. This can be used to support both Python 2 and
+# 3 compatible code, which means that the block might have code that exists
+# only in one or another interpreter, leading to false positives when analysed.
+analyse-fallback-blocks=no
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=optparse,tkinter.tix
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+
+[CLASSES]
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,_fields,_replace,_source,_make
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=mcs
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Maximum number of attributes for a class (see R0902).
+# max-attributes=7
+max-attributes=11
+
+# Maximum number of boolean expressions in a if statement
+max-bool-expr=5
+
+# Maximum number of branch for function / method body
+max-branches=12
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=1
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/.readthedocs.yaml b/circuitpython/frozen/Adafruit_CircuitPython_HID/.readthedocs.yaml
new file mode 100644
index 0000000..f8b2891
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/.readthedocs.yaml
@@ -0,0 +1,15 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: Unlicense
+
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+python:
+ version: "3.x"
+ install:
+ - requirements: docs/requirements.txt
+ - requirements: requirements.txt
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/CODE_OF_CONDUCT.md b/circuitpython/frozen/Adafruit_CircuitPython_HID/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..8a55c07
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/CODE_OF_CONDUCT.md
@@ -0,0 +1,135 @@
+<!--
+SPDX-FileCopyrightText: 2014 Coraline Ada Ehmke
+SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
+SPDX-License-Identifier: CC-BY-4.0
+-->
+
+# Adafruit Community Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and leaders pledge to making participation in our project and
+our community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, gender identity and expression, level or type of
+experience, education, socio-economic status, nationality, personal appearance,
+race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+We are committed to providing a friendly, safe and welcoming environment for
+all.
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Be kind and courteous to others
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Collaborating with other community members
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and sexual attention or advances
+* The use of inappropriate images, including in a community member's avatar
+* The use of inappropriate language, including in a community member's nickname
+* Any spamming, flaming, baiting or other attention-stealing behavior
+* Excessive or unwelcome helping; answering outside the scope of the question
+ asked
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Promoting or spreading disinformation, lies, or conspiracy theories against
+ a person, group, organisation, project, or community
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate
+
+The goal of the standards and moderation guidelines outlined here is to build
+and maintain a respectful community. We ask that you don’t just aim to be
+"technically unimpeachable", but rather try to be your best self.
+
+We value many things beyond technical expertise, including collaboration and
+supporting others within our community. Providing a positive experience for
+other community members can have a much more significant impact than simply
+providing the correct answer.
+
+## Our Responsibilities
+
+Project leaders are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project leaders have the right and responsibility to remove, edit, or
+reject messages, comments, commits, code, issues, and other contributions
+that are not aligned to this Code of Conduct, or to ban temporarily or
+permanently any community member for other behaviors that they deem
+inappropriate, threatening, offensive, or harmful.
+
+## Moderation
+
+Instances of behaviors that violate the Adafruit Community Code of Conduct
+may be reported by any member of the community. Community members are
+encouraged to report these situations, including situations they witness
+involving other community members.
+
+You may report in the following ways:
+
+In any situation, you may send an email to <support@adafruit.com>.
+
+On the Adafruit Discord, you may send an open message from any channel
+to all Community Moderators by tagging @community moderators. You may
+also send an open message from any channel, or a direct message to
+@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
+@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
+
+Email and direct message reports will be kept confidential.
+
+In situations on Discord where the issue is particularly egregious, possibly
+illegal, requires immediate action, or violates the Discord terms of service,
+you should also report the message directly to Discord.
+
+These are the steps for upholding our community’s standards of conduct.
+
+1. Any member of the community may report any situation that violates the
+Adafruit Community Code of Conduct. All reports will be reviewed and
+investigated.
+2. If the behavior is an egregious violation, the community member who
+committed the violation may be banned immediately, without warning.
+3. Otherwise, moderators will first respond to such behavior with a warning.
+4. Moderators follow a soft "three strikes" policy - the community member may
+be given another chance, if they are receptive to the warning and change their
+behavior.
+5. If the community member is unreceptive or unreasonable when warned by a
+moderator, or the warning goes unheeded, they may be banned for a first or
+second offense. Repeated offenses will result in the community member being
+banned.
+
+## Scope
+
+This Code of Conduct and the enforcement policies listed above apply to all
+Adafruit Community venues. This includes but is not limited to any community
+spaces (both public and private), the entire Adafruit Discord server, and
+Adafruit GitHub repositories. Examples of Adafruit Community spaces include
+but are not limited to meet-ups, audio chats on the Adafruit Discord, or
+interaction at a conference.
+
+This Code of Conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community. As a community
+member, you are representing our community, and are expected to behave
+accordingly.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.4, available at
+<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
+and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
+
+For other projects adopting the Adafruit Community Code of
+Conduct, please contact the maintainers of those projects for enforcement.
+If you wish to use this code of conduct for your own project, consider
+explicitly mentioning your moderation policy or making a copy with your
+own moderation policy so as to avoid confusion.
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSE b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSE
new file mode 100644
index 0000000..de855cb
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/CC-BY-4.0.txt b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/CC-BY-4.0.txt
new file mode 100644
index 0000000..3f92dfc
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/CC-BY-4.0.txt
@@ -0,0 +1,324 @@
+Creative Commons Attribution 4.0 International Creative Commons Corporation
+("Creative Commons") is not a law firm and does not provide legal services
+or legal advice. Distribution of Creative Commons public licenses does not
+create a lawyer-client or other relationship. Creative Commons makes its licenses
+and related information available on an "as-is" basis. Creative Commons gives
+no warranties regarding its licenses, any material licensed under their terms
+and conditions, or any related information. Creative Commons disclaims all
+liability for damages resulting from their use to the fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and conditions
+that creators and other rights holders may use to share original works of
+authorship and other material subject to copyright and certain other rights
+specified in the public license below. The following considerations are for
+informational purposes only, are not exhaustive, and do not form part of our
+licenses.
+
+Considerations for licensors: Our public licenses are intended for use by
+those authorized to give the public permission to use material in ways otherwise
+restricted by copyright and certain other rights. Our licenses are irrevocable.
+Licensors should read and understand the terms and conditions of the license
+they choose before applying it. Licensors should also secure all rights necessary
+before applying our licenses so that the public can reuse the material as
+expected. Licensors should clearly mark any material not subject to the license.
+This includes other CC-licensed material, or material used under an exception
+or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors
+
+Considerations for the public: By using one of our public licenses, a licensor
+grants the public permission to use the licensed material under specified
+terms and conditions. If the licensor's permission is not necessary for any
+reason–for example, because of any applicable exception or limitation to copyright–then
+that use is not regulated by the license. Our licenses grant only permissions
+under copyright and certain other rights that a licensor has authority to
+grant. Use of the licensed material may still be restricted for other reasons,
+including because others have copyright or other rights in the material. A
+licensor may make special requests, such as asking that all changes be marked
+or described. Although not required by our licenses, you are encouraged to
+respect those requests where reasonable. More considerations for the public
+: wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution
+4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree to
+be bound by the terms and conditions of this Creative Commons Attribution
+4.0 International Public License ("Public License"). To the extent this Public
+License may be interpreted as a contract, You are granted the Licensed Rights
+in consideration of Your acceptance of these terms and conditions, and the
+Licensor grants You such rights in consideration of benefits the Licensor
+receives from making the Licensed Material available under these terms and
+conditions.
+
+Section 1 – Definitions.
+
+a. Adapted Material means material subject to Copyright and Similar Rights
+that is derived from or based upon the Licensed Material and in which the
+Licensed Material is translated, altered, arranged, transformed, or otherwise
+modified in a manner requiring permission under the Copyright and Similar
+Rights held by the Licensor. For purposes of this Public License, where the
+Licensed Material is a musical work, performance, or sound recording, Adapted
+Material is always produced where the Licensed Material is synched in timed
+relation with a moving image.
+
+b. Adapter's License means the license You apply to Your Copyright and Similar
+Rights in Your contributions to Adapted Material in accordance with the terms
+and conditions of this Public License.
+
+c. Copyright and Similar Rights means copyright and/or similar rights closely
+related to copyright including, without limitation, performance, broadcast,
+sound recording, and Sui Generis Database Rights, without regard to how the
+rights are labeled or categorized. For purposes of this Public License, the
+rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
+
+d. Effective Technological Measures means those measures that, in the absence
+of proper authority, may not be circumvented under laws fulfilling obligations
+under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996,
+and/or similar international agreements.
+
+e. Exceptions and Limitations means fair use, fair dealing, and/or any other
+exception or limitation to Copyright and Similar Rights that applies to Your
+use of the Licensed Material.
+
+f. Licensed Material means the artistic or literary work, database, or other
+material to which the Licensor applied this Public License.
+
+g. Licensed Rights means the rights granted to You subject to the terms and
+conditions of this Public License, which are limited to all Copyright and
+Similar Rights that apply to Your use of the Licensed Material and that the
+Licensor has authority to license.
+
+h. Licensor means the individual(s) or entity(ies) granting rights under this
+Public License.
+
+i. Share means to provide material to the public by any means or process that
+requires permission under the Licensed Rights, such as reproduction, public
+display, public performance, distribution, dissemination, communication, or
+importation, and to make material available to the public including in ways
+that members of the public may access the material from a place and at a time
+individually chosen by them.
+
+j. Sui Generis Database Rights means rights other than copyright resulting
+from Directive 96/9/EC of the European Parliament and of the Council of 11
+March 1996 on the legal protection of databases, as amended and/or succeeded,
+as well as other essentially equivalent rights anywhere in the world.
+
+k. You means the individual or entity exercising the Licensed Rights under
+this Public License. Your has a corresponding meaning.
+
+Section 2 – Scope.
+
+ a. License grant.
+
+1. Subject to the terms and conditions of this Public License, the Licensor
+hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive,
+irrevocable license to exercise the Licensed Rights in the Licensed Material
+to:
+
+ A. reproduce and Share the Licensed Material, in whole or in part; and
+
+ B. produce, reproduce, and Share Adapted Material.
+
+2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions
+and Limitations apply to Your use, this Public License does not apply, and
+You do not need to comply with its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section 6(a).
+
+4. Media and formats; technical modifications allowed. The Licensor authorizes
+You to exercise the Licensed Rights in all media and formats whether now known
+or hereafter created, and to make technical modifications necessary to do
+so. The Licensor waives and/or agrees not to assert any right or authority
+to forbid You from making technical modifications necessary to exercise the
+Licensed Rights, including technical modifications necessary to circumvent
+Effective Technological Measures. For purposes of this Public License, simply
+making modifications authorized by this Section 2(a)(4) never produces Adapted
+Material.
+
+ 5. Downstream recipients.
+
+A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed
+Material automatically receives an offer from the Licensor to exercise the
+Licensed Rights under the terms and conditions of this Public License.
+
+B. No downstream restrictions. You may not offer or impose any additional
+or different terms or conditions on, or apply any Effective Technological
+Measures to, the Licensed Material if doing so restricts exercise of the Licensed
+Rights by any recipient of the Licensed Material.
+
+6. No endorsement. Nothing in this Public License constitutes or may be construed
+as permission to assert or imply that You are, or that Your use of the Licensed
+Material is, connected with, or sponsored, endorsed, or granted official status
+by, the Licensor or others designated to receive attribution as provided in
+Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+1. Moral rights, such as the right of integrity, are not licensed under this
+Public License, nor are publicity, privacy, and/or other similar personality
+rights; however, to the extent possible, the Licensor waives and/or agrees
+not to assert any such rights held by the Licensor to the limited extent necessary
+to allow You to exercise the Licensed Rights, but not otherwise.
+
+2. Patent and trademark rights are not licensed under this Public License.
+
+3. To the extent possible, the Licensor waives any right to collect royalties
+from You for the exercise of the Licensed Rights, whether directly or through
+a collecting society under any voluntary or waivable statutory or compulsory
+licensing scheme. In all other cases the Licensor expressly reserves any right
+to collect such royalties.
+
+Section 3 – License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the following
+conditions.
+
+ a. Attribution.
+
+1. If You Share the Licensed Material (including in modified form), You must:
+
+A. retain the following if it is supplied by the Licensor with the Licensed
+Material:
+
+i. identification of the creator(s) of the Licensed Material and any others
+designated to receive attribution, in any reasonable manner requested by the
+Licensor (including by pseudonym if designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of warranties;
+
+v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
+
+B. indicate if You modified the Licensed Material and retain an indication
+of any previous modifications; and
+
+C. indicate the Licensed Material is licensed under this Public License, and
+include the text of, or the URI or hyperlink to, this Public License.
+
+2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner
+based on the medium, means, and context in which You Share the Licensed Material.
+For example, it may be reasonable to satisfy the conditions by providing a
+URI or hyperlink to a resource that includes the required information.
+
+3. If requested by the Licensor, You must remove any of the information required
+by Section 3(a)(1)(A) to the extent reasonably practicable.
+
+4. If You Share Adapted Material You produce, the Adapter's License You apply
+must not prevent recipients of the Adapted Material from complying with this
+Public License.
+
+Section 4 – Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that apply to
+Your use of the Licensed Material:
+
+a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract,
+reuse, reproduce, and Share all or a substantial portion of the contents of
+the database;
+
+b. if You include all or a substantial portion of the database contents in
+a database in which You have Sui Generis Database Rights, then the database
+in which You have Sui Generis Database Rights (but not its individual contents)
+is Adapted Material; and
+
+c. You must comply with the conditions in Section 3(a) if You Share all or
+a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not replace
+Your obligations under this Public License where the Licensed Rights include
+other Copyright and Similar Rights.
+
+Section 5 – Disclaimer of Warranties and Limitation of Liability.
+
+a. Unless otherwise separately undertaken by the Licensor, to the extent possible,
+the Licensor offers the Licensed Material as-is and as-available, and makes
+no representations or warranties of any kind concerning the Licensed Material,
+whether express, implied, statutory, or other. This includes, without limitation,
+warranties of title, merchantability, fitness for a particular purpose, non-infringement,
+absence of latent or other defects, accuracy, or the presence or absence of
+errors, whether or not known or discoverable. Where disclaimers of warranties
+are not allowed in full or in part, this disclaimer may not apply to You.
+
+b. To the extent possible, in no event will the Licensor be liable to You
+on any legal theory (including, without limitation, negligence) or otherwise
+for any direct, special, indirect, incidental, consequential, punitive, exemplary,
+or other losses, costs, expenses, or damages arising out of this Public License
+or use of the Licensed Material, even if the Licensor has been advised of
+the possibility of such losses, costs, expenses, or damages. Where a limitation
+of liability is not allowed in full or in part, this limitation may not apply
+to You.
+
+c. The disclaimer of warranties and limitation of liability provided above
+shall be interpreted in a manner that, to the extent possible, most closely
+approximates an absolute disclaimer and waiver of all liability.
+
+Section 6 – Term and Termination.
+
+a. This Public License applies for the term of the Copyright and Similar Rights
+licensed here. However, if You fail to comply with this Public License, then
+Your rights under this Public License terminate automatically.
+
+b. Where Your right to use the Licensed Material has terminated under Section
+6(a), it reinstates:
+
+1. automatically as of the date the violation is cured, provided it is cured
+within 30 days of Your discovery of the violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+c. For the avoidance of doubt, this Section 6(b) does not affect any right
+the Licensor may have to seek remedies for Your violations of this Public
+License.
+
+d. For the avoidance of doubt, the Licensor may also offer the Licensed Material
+under separate terms or conditions or stop distributing the Licensed Material
+at any time; however, doing so will not terminate this Public License.
+
+ e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.
+
+Section 7 – Other Terms and Conditions.
+
+a. The Licensor shall not be bound by any additional or different terms or
+conditions communicated by You unless expressly agreed.
+
+b. Any arrangements, understandings, or agreements regarding the Licensed
+Material not stated herein are separate from and independent of the terms
+and conditions of this Public License.
+
+Section 8 – Interpretation.
+
+a. For the avoidance of doubt, this Public License does not, and shall not
+be interpreted to, reduce, limit, restrict, or impose conditions on any use
+of the Licensed Material that could lawfully be made without permission under
+this Public License.
+
+b. To the extent possible, if any provision of this Public License is deemed
+unenforceable, it shall be automatically reformed to the minimum extent necessary
+to make it enforceable. If the provision cannot be reformed, it shall be severed
+from this Public License without affecting the enforceability of the remaining
+terms and conditions.
+
+c. No term or condition of this Public License will be waived and no failure
+to comply consented to unless expressly agreed to by the Licensor.
+
+d. Nothing in this Public License constitutes or may be interpreted as a limitation
+upon, or waiver of, any privileges and immunities that apply to the Licensor
+or You, including from the legal processes of any jurisdiction or authority.
+
+Creative Commons is not a party to its public licenses. Notwithstanding, Creative
+Commons may elect to apply one of its public licenses to material it publishes
+and in those instances will be considered the "Licensor." The text of the
+Creative Commons public licenses is dedicated to the public domain under the
+CC0 Public Domain Dedication. Except for the limited purpose of indicating
+that material is shared under a Creative Commons public license or as otherwise
+permitted by the Creative Commons policies published at creativecommons.org/policies,
+Creative Commons does not authorize the use of the trademark "Creative Commons"
+or any other trademark or logo of Creative Commons without its prior written
+consent including, without limitation, in connection with any unauthorized
+modifications to any of its public licenses or any other arrangements, understandings,
+or agreements concerning use of licensed material. For the avoidance of doubt,
+this paragraph does not form part of the public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/MIT.txt b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/MIT.txt
new file mode 100644
index 0000000..204b93d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/MIT.txt
@@ -0,0 +1,19 @@
+MIT License Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/Unlicense.txt b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/Unlicense.txt
new file mode 100644
index 0000000..24a8f90
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/LICENSES/Unlicense.txt
@@ -0,0 +1,20 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or distribute
+this software, either in source code form or as a compiled binary, for any
+purpose, commercial or non-commercial, and by any means.
+
+In jurisdictions that recognize copyright laws, the author or authors of this
+software dedicate any and all copyright interest in the software to the public
+domain. We make this dedication for the benefit of the public at large and
+to the detriment of our heirs and successors. We intend this dedication to
+be an overt act of relinquishment in perpetuity of all present and future
+rights to this software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
+THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information,
+please refer to <https://unlicense.org/>
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst b/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst
new file mode 100644
index 0000000..1c5780f
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst
@@ -0,0 +1,160 @@
+
+Introduction
+============
+
+.. image:: https://readthedocs.org/projects/adafruit-circuitpython-hid/badge/?version=latest
+ :target: https://docs.circuitpython.org/projects/hid/en/latest/
+ :alt: Documentation Status
+
+.. image :: https://img.shields.io/discord/327254708534116352.svg
+ :target: https://adafru.it/discord
+ :alt: Discord
+
+.. image:: https://github.com/adafruit/Adafruit_CircuitPython_HID/workflows/Build%20CI/badge.svg
+ :target: https://github.com/adafruit/Adafruit_CircuitPython_HID/actions/
+ :alt: Build Status
+
+
+This driver simulates USB HID devices. Currently keyboard and mouse are implemented.
+
+Dependencies
+=============
+This driver depends on:
+
+* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
+
+Please ensure all dependencies are available on the CircuitPython filesystem.
+This is easily achieved by downloading
+`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
+
+Additional Layouts
+====================
+This library has an en-US layout. Please check out and expand `the library from Neradoc <https://github.com/Neradoc/Circuitpython_Keyboard_Layouts>`_ for additional layouts.
+
+Usage Example
+=============
+
+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
+ from adafruit_hid.keyboard import Keyboard
+ from adafruit_hid.keycode import Keycode
+
+ # Set up a keyboard device.
+ kbd = Keyboard(usb_hid.devices)
+
+ # Type lowercase 'a'. Presses the 'a' key and releases it.
+ kbd.send(Keycode.A)
+
+ # Type capital 'A'.
+ kbd.send(Keycode.SHIFT, Keycode.A)
+
+ # Type control-x.
+ kbd.send(Keycode.CONTROL, Keycode.X)
+
+ # You can also control press and release actions separately.
+ kbd.press(Keycode.CONTROL, Keycode.X)
+ 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 ``KeyboardLayoutUS`` 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
+``KeyboardLayoutUS`` 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 ``KeyboardLayoutUS``. More ``KeyboardLayout``
+classes could be added to handle non-US keyboards and the different input methods provided
+by various operating systems.
+
+.. code-block:: python
+
+ import usb_hid
+ from adafruit_hid.keyboard import Keyboard
+ from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
+
+ kbd = Keyboard(usb_hid.devices)
+ layout = KeyboardLayoutUS(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.
+
+.. code-block:: python
+
+ import usb_hid
+ from adafruit_hid.mouse import Mouse
+
+ m = Mouse(usb_hid.devices)
+
+ # Click the left mouse button.
+ m.click(Mouse.LEFT_BUTTON)
+
+ # Move the mouse diagonally to the upper left.
+ m.move(-100, -100, 0)
+
+ # Roll the mouse wheel away from the user one unit.
+ # Amount scrolled depends on the host.
+ m.move(0, 0, -1)
+
+ # Keyword arguments may also be used. Omitted arguments default to 0.
+ m.move(x=-100, y=-100)
+ m.move(wheel=-1)
+
+ # Move the mouse while holding down the left button. (click-drag).
+ m.press(Mouse.LEFT_BUTTON)
+ m.move(x=50, y=20)
+ m.release_all() # or m.release(Mouse.LEFT_BUTTON)
+
+The ``ConsumerControl`` class emulates consumer control devices such as
+remote controls, or the multimedia keys on certain keyboards.
+
+.. code-block:: python
+
+ import usb_hid
+ from adafruit_hid.consumer_control import ConsumerControl
+ from adafruit_hid.consumer_control_code import ConsumerControlCode
+
+ cc = ConsumerControl(usb_hid.devices)
+
+ # Raise volume.
+ cc.send(ConsumerControlCode.VOLUME_INCREMENT)
+
+ # Pause or resume playback.
+ cc.send(ConsumerControlCode.PLAY_PAUSE)
+
+Documentation
+=============
+
+API documentation for this library can be found on `Read the Docs <https://docs.circuitpython.org/projects/hid/en/latest/>`_.
+
+Contributing
+============
+
+Contributions are welcome! Please read our `Code of Conduct
+<https://github.com/adafruit/Adafruit_CircuitPython_hid/blob/main/CODE_OF_CONDUCT.md>`_
+before contributing to help this project stay welcoming.
+
+Documentation
+=============
+
+For information on building library documentation, please check out `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst.license b/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst.license
new file mode 100644
index 0000000..11cd75d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/README.rst.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
+
+SPDX-License-Identifier: MIT
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/__init__.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/__init__.py
new file mode 100644
index 0000000..518817d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/__init__.py
@@ -0,0 +1,45 @@
+# SPDX-FileCopyrightText: 2017 Scott Shawcroft for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid`
+====================================================
+
+This driver simulates USB HID devices.
+
+* Author(s): Scott Shawcroft, Dan Halbert
+
+Implementation Notes
+--------------------
+**Software and Dependencies:**
+* Adafruit CircuitPython firmware for the supported boards:
+ https://github.com/adafruit/circuitpython/releases
+"""
+
+# imports
+try:
+ from typing import Sequence
+ import usb_hid
+except ImportError:
+ pass
+
+__version__ = "0.0.0-auto.0"
+__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_HID.git"
+
+
+def find_device(
+ devices: Sequence[usb_hid.Device], *, usage_page: int, usage: int
+) -> usb_hid.Device:
+ """Search through the provided sequence of devices to find the one with the matching
+ usage_page and usage."""
+ if hasattr(devices, "send_report"):
+ devices = [devices]
+ for device in devices:
+ if (
+ device.usage_page == usage_page
+ and device.usage == usage
+ and hasattr(device, "send_report")
+ ):
+ return device
+ raise ValueError("Could not find matching HID device.")
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control.py
new file mode 100644
index 0000000..d26f116
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control.py
@@ -0,0 +1,106 @@
+# SPDX-FileCopyrightText: 2018 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.consumer_control.ConsumerControl`
+====================================================
+
+* Author(s): Dan Halbert
+"""
+
+import sys
+
+if sys.implementation.version[0] < 3:
+ raise ImportError(
+ "{0} is not supported in CircuitPython 2.x or lower".format(__name__)
+ )
+
+# pylint: disable=wrong-import-position
+import struct
+import time
+from . import find_device
+
+try:
+ from typing import Sequence
+ import usb_hid
+except ImportError:
+ pass
+
+
+class ConsumerControl:
+ """Send ConsumerControl code reports, used by multimedia keyboards, remote controls, etc."""
+
+ def __init__(self, devices: Sequence[usb_hid.Device]) -> None:
+ """Create a ConsumerControl object that will send Consumer Control Device HID reports.
+
+ Devices can be a sequence of devices that includes a Consumer Control device or a CC device
+ itself. A device is any object that implements ``send_report()``, ``usage_page`` and
+ ``usage``.
+ """
+ self._consumer_device = find_device(devices, usage_page=0x0C, usage=0x01)
+
+ # Reuse this bytearray to send consumer reports.
+ self._report = bytearray(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)
+
+ def send(self, consumer_code: int) -> None:
+ """Send a report to do the specified consumer control action,
+ and then stop the action (so it will not repeat).
+
+ :param consumer_code: a 16-bit consumer control code.
+
+ Examples::
+
+ from adafruit_hid.consumer_control_code import ConsumerControlCode
+
+ # Raise volume.
+ consumer_control.send(ConsumerControlCode.VOLUME_INCREMENT)
+
+ # Advance to next track (song).
+ consumer_control.send(ConsumerControlCode.SCAN_NEXT_TRACK)
+ """
+ self.press(consumer_code)
+ self.release()
+
+ def press(self, consumer_code: int) -> None:
+ """Send a report to indicate that the given key has been pressed.
+ Only one consumer control action can be pressed at a time, so any one
+ that was previously pressed will be released.
+
+ :param consumer_code: a 16-bit consumer control code.
+
+ Examples::
+
+ from adafruit_hid.consumer_control_code import ConsumerControlCode
+
+ # Raise volume for 0.5 seconds
+ consumer_control.press(ConsumerControlCode.VOLUME_INCREMENT)
+ time.sleep(0.5)
+ consumer_control.release()
+ """
+ struct.pack_into("<H", self._report, 0, consumer_code)
+ self._consumer_device.send_report(self._report)
+
+ def release(self) -> None:
+ """Send a report indicating that the consumer control key has been
+ released. Only one consumer control key can be pressed at a time.
+
+ Examples::
+
+ from adafruit_hid.consumer_control_code import ConsumerControlCode
+
+ # Raise volume for 0.5 seconds
+ consumer_control.press(ConsumerControlCode.VOLUME_INCREMENT)
+ time.sleep(0.5)
+ consumer_control.release()
+ """
+ self._report[0] = self._report[1] = 0x0
+ self._consumer_device.send_report(self._report)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control_code.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control_code.py
new file mode 100644
index 0000000..e49137e
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/consumer_control_code.py
@@ -0,0 +1,47 @@
+# SPDX-FileCopyrightText: 2018 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.consumer_control_code.ConsumerControlCode`
+========================================================
+
+* Author(s): Dan Halbert
+"""
+
+
+class ConsumerControlCode:
+ """USB HID Consumer Control Device constants.
+
+ This list includes a few common consumer control codes from
+ https://www.usb.org/sites/default/files/hut1_21_0.pdf#page=118.
+ """
+
+ # pylint: disable-msg=too-few-public-methods
+
+ RECORD = 0xB2
+ """Record"""
+ FAST_FORWARD = 0xB3
+ """Fast Forward"""
+ REWIND = 0xB4
+ """Rewind"""
+ SCAN_NEXT_TRACK = 0xB5
+ """Skip to next track"""
+ SCAN_PREVIOUS_TRACK = 0xB6
+ """Go back to previous track"""
+ STOP = 0xB7
+ """Stop"""
+ EJECT = 0xB8
+ """Eject"""
+ PLAY_PAUSE = 0xCD
+ """Play/Pause toggle"""
+ MUTE = 0xE2
+ """Mute"""
+ VOLUME_DECREMENT = 0xEA
+ """Decrease volume"""
+ VOLUME_INCREMENT = 0xE9
+ """Increase volume"""
+ BRIGHTNESS_DECREMENT = 0x70
+ """Decrease Brightness"""
+ BRIGHTNESS_INCREMENT = 0x6F
+ """Increase Brightness"""
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard.py
new file mode 100644
index 0000000..f1240c3
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard.py
@@ -0,0 +1,189 @@
+# SPDX-FileCopyrightText: 2017 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.keyboard.Keyboard`
+====================================================
+
+* Author(s): Scott Shawcroft, Dan Halbert
+"""
+
+import time
+from micropython import const
+
+from .keycode import Keycode
+
+from . import find_device
+
+try:
+ from typing import Sequence
+ import usb_hid
+except ImportError:
+ pass
+
+_MAX_KEYPRESSES = const(6)
+
+
+class Keyboard:
+ """Send HID keyboard reports."""
+
+ LED_NUM_LOCK = 0x01
+ """LED Usage ID for Num Lock"""
+ LED_CAPS_LOCK = 0x02
+ """LED Usage ID for Caps Lock"""
+ LED_SCROLL_LOCK = 0x04
+ """LED Usage ID for Scroll Lock"""
+ LED_COMPOSE = 0x08
+ """LED Usage ID for Compose"""
+
+ # No more than _MAX_KEYPRESSES regular keys may be pressed at once.
+
+ def __init__(self, devices: Sequence[usb_hid.Device]) -> None:
+ """Create a Keyboard object that will send keyboard HID reports.
+
+ Devices can be a sequence of devices that includes a keyboard device or a keyboard device
+ itself. A device is any object that implements ``send_report()``, ``usage_page`` and
+ ``usage``.
+ """
+ self._keyboard_device = find_device(devices, usage_page=0x1, usage=0x06)
+
+ # Reuse this bytearray to send keyboard reports.
+ self.report = bytearray(8)
+
+ # report[0] modifiers
+ # report[1] unused
+ # report[2:8] regular key presses
+
+ # View onto byte 0 in report.
+ self.report_modifier = memoryview(self.report)[0:1]
+
+ # List of regular keys currently pressed.
+ # 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: int) -> None:
+ """Send a report indicating that the given keys have been pressed.
+
+ :param keycodes: Press these keycodes all at once.
+ :raises ValueError: if more than six regular keys are pressed.
+
+ Keycodes may be modifiers or regular keys.
+ No more than six regular keys may be pressed simultaneously.
+
+ Examples::
+
+ from adafruit_hid.keycode import Keycode
+
+ # Press ctrl-x.
+ kbd.press(Keycode.LEFT_CONTROL, Keycode.X)
+
+ # Or, more conveniently, use the CONTROL alias for LEFT_CONTROL:
+ kbd.press(Keycode.CONTROL, Keycode.X)
+
+ # Press a, b, c keys all at once.
+ kbd.press(Keycode.A, Keycode.B, Keycode.C)
+ """
+ for keycode in keycodes:
+ self._add_keycode_to_report(keycode)
+ self._keyboard_device.send_report(self.report)
+
+ def release(self, *keycodes: int) -> None:
+ """Send a USB HID report indicating that the given keys have been released.
+
+ :param keycodes: Release these keycodes all at once.
+
+ If a keycode to be released was not pressed, it is ignored.
+
+ Example::
+
+ # release SHIFT key
+ kbd.release(Keycode.SHIFT)
+ """
+ for keycode in keycodes:
+ self._remove_keycode_from_report(keycode)
+ self._keyboard_device.send_report(self.report)
+
+ def release_all(self) -> None:
+ """Release all pressed keys."""
+ for i in range(8):
+ self.report[i] = 0
+ self._keyboard_device.send_report(self.report)
+
+ def send(self, *keycodes: int) -> None:
+ """Press the given keycodes and then release all pressed keys.
+
+ :param keycodes: keycodes to send together
+ """
+ self.press(*keycodes)
+ self.release_all()
+
+ def _add_keycode_to_report(self, keycode: int) -> None:
+ """Add a single keycode to the USB HID report."""
+ modifier = Keycode.modifier_bit(keycode)
+ if modifier:
+ # Set bit for this modifier.
+ self.report_modifier[0] |= modifier
+ else:
+ # Don't press twice.
+ # (I'd like to use 'not in self.report_keys' here, but that's not implemented.)
+ for i in range(_MAX_KEYPRESSES):
+ if self.report_keys[i] == keycode:
+ # Already pressed.
+ return
+ # Put keycode in first empty slot.
+ for i in range(_MAX_KEYPRESSES):
+ if self.report_keys[i] == 0:
+ self.report_keys[i] = keycode
+ return
+ # All slots are filled.
+ raise ValueError("Trying to press more than six keys at once.")
+
+ def _remove_keycode_from_report(self, keycode: int) -> None:
+ """Remove a single keycode from the report."""
+ modifier = Keycode.modifier_bit(keycode)
+ if modifier:
+ # Turn off the bit for this modifier.
+ self.report_modifier[0] &= ~modifier
+ else:
+ # Check all the slots, just in case there's a duplicate. (There should not be.)
+ for i in range(_MAX_KEYPRESSES):
+ if self.report_keys[i] == keycode:
+ self.report_keys[i] = 0
+
+ @property
+ def led_status(self) -> bytes:
+ """Returns the last received report"""
+ return self._keyboard_device.last_received_report
+
+ def led_on(self, led_code: int) -> bool:
+ """Returns whether an LED is on based on the led code
+
+ Examples::
+
+ import usb_hid
+ from adafruit_hid.keyboard import Keyboard
+ from adafruit_hid.keycode import Keycode
+ import time
+
+ # Initialize Keybaord
+ kbd = Keyboard(usb_hid.devices)
+
+ # Press and release CapsLock.
+ kbd.press(Keycode.CAPS_LOCK)
+ time.sleep(.09)
+ kbd.release(Keycode.CAPS_LOCK)
+
+ # Check status of the LED_CAPS_LOCK
+ print(kbd.led_on(Keyboard.LED_CAPS_LOCK))
+
+ """
+ return bool(self.led_status[0] & led_code)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_base.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_base.py
new file mode 100755
index 0000000..54de33d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_base.py
@@ -0,0 +1,186 @@
+# SPDX-FileCopyrightText: 2017 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.keyboard_layout_base.KeyboardLayoutBase`
+=======================================================
+
+* Author(s): Dan Halbert, AngainorDev, Neradoc
+"""
+
+
+try:
+ from typing import Tuple
+ from .keyboard import Keyboard
+except ImportError:
+ pass
+
+
+__version__ = "0.0.0-auto.0"
+__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_HID.git"
+
+
+class KeyboardLayoutBase:
+ """Base class for keyboard layouts. Uses the tables defined in the subclass
+ to map UTF-8 characters to appropriate keypresses.
+
+ Non-supported characters and most control characters will raise an exception.
+ """
+
+ SHIFT_FLAG = 0x80
+ """Bit set in any keycode byte if the shift key is required for the character."""
+ ALTGR_FLAG = 0x80
+ """Bit set in the combined keys table if altgr is required for the first key."""
+ SHIFT_CODE = 0xE1
+ """The SHIFT keycode, to avoid dependency to the Keycode class."""
+ RIGHT_ALT_CODE = 0xE6
+ """The ALTGR keycode, to avoid dependency to the Keycode class."""
+ ASCII_TO_KEYCODE = ()
+ """Bytes string of keycodes for low ASCII characters, indexed by the ASCII value.
+ Keycodes use the `SHIFT_FLAG` if needed.
+ Dead keys are excluded by assigning the keycode 0."""
+ HIGHER_ASCII = {}
+ """Dictionary that associates the ord() int value of high ascii and utf8 characters
+ to their keycode. Keycodes use the `SHIFT_FLAG` if needed."""
+ NEED_ALTGR = ""
+ """Characters in `ASCII_TO_KEYCODE` and `HIGHER_ASCII` that need
+ the ALTGR key pressed to type."""
+ COMBINED_KEYS = {}
+ """
+ Dictionary of characters (indexed by ord() value) that can be accessed by typing first
+ a dead key followed by a regular key, like ``ñ`` as ``~ + n``. The value is a 2-bytes int:
+ the high byte is the dead-key keycode (including SHIFT_FLAG), the low byte is the ascii code
+ of the second character, with ALTGR_FLAG set if the dead key (the first key) needs ALTGR.
+
+ The combined-key codes bits are: ``0b SDDD DDDD AKKK KKKK``:
+ ``S`` is the shift flag for the **first** key,
+ ``DDD DDDD`` is the keycode for the **first** key,
+ ``A`` is the altgr flag for the **first** key,
+ ``KKK KKKK`` is the (low) ASCII code for the second character.
+ """
+
+ def __init__(self, keyboard: Keyboard) -> None:
+ """Specify the layout for the given keyboard.
+
+ :param keyboard: a Keyboard object. Write characters to this keyboard when requested.
+
+ Example::
+
+ kbd = Keyboard(usb_hid.devices)
+ layout = KeyboardLayout(kbd)
+ """
+ self.keyboard = keyboard
+
+ def _write(self, keycode: int, altgr: bool = False) -> None:
+ """Type a key combination based on shift bit and altgr bool
+
+ :param keycode: int value of the keycode, with the shift bit.
+ :param altgr: bool indicating if the altgr key should be pressed too.
+ """
+ # Add altgr modifier if needed
+ if altgr:
+ self.keyboard.press(self.RIGHT_ALT_CODE)
+ # If this is a shifted char, clear the SHIFT flag and press the SHIFT key.
+ if keycode & self.SHIFT_FLAG:
+ keycode &= ~self.SHIFT_FLAG
+ self.keyboard.press(self.SHIFT_CODE)
+ self.keyboard.press(keycode)
+ self.keyboard.release_all()
+
+ def write(self, string: str) -> None:
+ """Type the string by pressing and releasing keys on my keyboard.
+
+ :param string: A string of UTF-8 characters to convert to key presses and send.
+ :raises ValueError: if any of the characters has no keycode
+ (such as some control characters).
+
+ Example::
+
+ # Write abc followed by Enter to the keyboard
+ layout.write('abc\\n')
+ """
+ for char in string:
+ # find easy ones first
+ keycode = self._char_to_keycode(char)
+ if keycode > 0:
+ self._write(keycode, char in self.NEED_ALTGR)
+ # find combined keys
+ elif ord(char) in self.COMBINED_KEYS:
+ # first key (including shift bit)
+ cchar = self.COMBINED_KEYS[ord(char)]
+ self._write(cchar >> 8, cchar & self.ALTGR_FLAG)
+ # second key (removing the altgr bit)
+ char = chr(cchar & 0xFF & (~self.ALTGR_FLAG))
+ keycode = self._char_to_keycode(char)
+ # assume no altgr needed for second key
+ self._write(keycode, False)
+ else:
+ raise ValueError(
+ "No keycode available for character {letter} ({num}/0x{num:02x}).".format(
+ letter=repr(char), num=ord(char)
+ )
+ )
+
+ def keycodes(self, char: str) -> Tuple[int, ...]:
+ """Return a tuple of keycodes needed to type the given character.
+
+ :param char: A single UTF8 character in a string.
+ :type char: str of length one.
+ :returns: tuple of Keycode keycodes.
+ :raises ValueError: if there is no keycode for ``char``.
+
+ Examples::
+
+ # Returns (Keycode.TAB,)
+ keycodes('\t')
+ # Returns (Keycode.A,)
+ keycode('a')
+ # Returns (Keycode.SHIFT, Keycode.A)
+ keycode('A')
+ # Raises ValueError with a US layout because it's an unknown character
+ keycode('é')
+ """
+ keycode = self._char_to_keycode(char)
+ if keycode == 0:
+ raise ValueError(
+ "No keycode available for character {letter} ({num}/0x{num:02x}).".format(
+ letter=repr(char), num=ord(char)
+ )
+ )
+
+ codes = []
+ if char in self.NEED_ALTGR:
+ codes.append(self.RIGHT_ALT_CODE)
+ if keycode & self.SHIFT_FLAG:
+ codes.extend((self.SHIFT_CODE, keycode & ~self.SHIFT_FLAG))
+ else:
+ codes.append(keycode)
+
+ return codes
+
+ def _above128char_to_keycode(self, char: str) -> int:
+ """Return keycode for above 128 utf8 codes.
+
+ A character can be indexed by the char itself or its int ord() value.
+
+ :param char_val: char value
+ :return: keycode, with modifiers if needed
+ """
+ if ord(char) in self.HIGHER_ASCII:
+ return self.HIGHER_ASCII[ord(char)]
+ if char in self.HIGHER_ASCII:
+ return self.HIGHER_ASCII[char]
+ return 0
+
+ def _char_to_keycode(self, char: str) -> int:
+ """Return the HID keycode for the given character, with the SHIFT_FLAG possibly set.
+
+ If the character requires pressing the Shift key, the SHIFT_FLAG bit is set.
+ You must clear this bit before passing the keycode in a USB report.
+ """
+ char_val = ord(char)
+ if char_val > len(self.ASCII_TO_KEYCODE):
+ return self._above128char_to_keycode(char)
+ keycode = self.ASCII_TO_KEYCODE[char_val]
+ return keycode
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_us.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_us.py
new file mode 100755
index 0000000..35b163b
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keyboard_layout_us.py
@@ -0,0 +1,166 @@
+# SPDX-FileCopyrightText: 2017 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.keyboard_layout_us.KeyboardLayoutUS`
+=======================================================
+
+* Author(s): Dan Halbert
+"""
+
+from .keyboard_layout_base import KeyboardLayoutBase
+
+
+class KeyboardLayoutUS(KeyboardLayoutBase):
+ """Map ASCII characters to appropriate keypresses on a standard US PC keyboard.
+
+ Non-ASCII characters and most control characters will raise an exception.
+ """
+
+ # The ASCII_TO_KEYCODE bytes object is used as a table to maps ASCII 0-127
+ # to the corresponding # keycode on a US 104-key keyboard.
+ # The user should not normally need to use this table,
+ # but it is not marked as private.
+ #
+ # Because the table only goes to 127, we use the top bit of each byte (ox80) to indicate
+ # that the shift key should be pressed. So any values 0x{8,9,a,b}* are shifted characters.
+ #
+ # The Python compiler will concatenate all these bytes literals into a single bytes object.
+ # Micropython/CircuitPython will store the resulting bytes constant in flash memory
+ # if it's in a .mpy file, so it doesn't use up valuable RAM.
+ #
+ # \x00 entries have no keyboard key and so won't be sent.
+ ASCII_TO_KEYCODE = (
+ b"\x00" # NUL
+ b"\x00" # SOH
+ b"\x00" # STX
+ b"\x00" # ETX
+ b"\x00" # EOT
+ b"\x00" # ENQ
+ b"\x00" # ACK
+ b"\x00" # BEL \a
+ b"\x2a" # BS BACKSPACE \b (called DELETE in the usb.org document)
+ b"\x2b" # TAB \t
+ b"\x28" # LF \n (called Return or ENTER in the usb.org document)
+ b"\x00" # VT \v
+ b"\x00" # FF \f
+ b"\x00" # CR \r
+ b"\x00" # SO
+ b"\x00" # SI
+ b"\x00" # DLE
+ b"\x00" # DC1
+ b"\x00" # DC2
+ b"\x00" # DC3
+ b"\x00" # DC4
+ b"\x00" # NAK
+ b"\x00" # SYN
+ b"\x00" # ETB
+ b"\x00" # CAN
+ b"\x00" # EM
+ b"\x00" # SUB
+ b"\x29" # ESC
+ b"\x00" # FS
+ b"\x00" # GS
+ b"\x00" # RS
+ b"\x00" # US
+ b"\x2c" # SPACE
+ b"\x9e" # ! x1e|SHIFT_FLAG (shift 1)
+ b"\xb4" # " x34|SHIFT_FLAG (shift ')
+ b"\xa0" # # x20|SHIFT_FLAG (shift 3)
+ b"\xa1" # $ x21|SHIFT_FLAG (shift 4)
+ b"\xa2" # % x22|SHIFT_FLAG (shift 5)
+ b"\xa4" # & x24|SHIFT_FLAG (shift 7)
+ b"\x34" # '
+ b"\xa6" # ( x26|SHIFT_FLAG (shift 9)
+ b"\xa7" # ) x27|SHIFT_FLAG (shift 0)
+ b"\xa5" # * x25|SHIFT_FLAG (shift 8)
+ b"\xae" # + x2e|SHIFT_FLAG (shift =)
+ b"\x36" # ,
+ b"\x2d" # -
+ b"\x37" # .
+ b"\x38" # /
+ b"\x27" # 0
+ b"\x1e" # 1
+ b"\x1f" # 2
+ b"\x20" # 3
+ b"\x21" # 4
+ b"\x22" # 5
+ b"\x23" # 6
+ b"\x24" # 7
+ b"\x25" # 8
+ b"\x26" # 9
+ b"\xb3" # : x33|SHIFT_FLAG (shift ;)
+ b"\x33" # ;
+ b"\xb6" # < x36|SHIFT_FLAG (shift ,)
+ b"\x2e" # =
+ b"\xb7" # > x37|SHIFT_FLAG (shift .)
+ b"\xb8" # ? x38|SHIFT_FLAG (shift /)
+ b"\x9f" # @ x1f|SHIFT_FLAG (shift 2)
+ b"\x84" # A x04|SHIFT_FLAG (shift a)
+ b"\x85" # B x05|SHIFT_FLAG (etc.)
+ b"\x86" # C x06|SHIFT_FLAG
+ b"\x87" # D x07|SHIFT_FLAG
+ b"\x88" # E x08|SHIFT_FLAG
+ b"\x89" # F x09|SHIFT_FLAG
+ b"\x8a" # G x0a|SHIFT_FLAG
+ b"\x8b" # H x0b|SHIFT_FLAG
+ b"\x8c" # I x0c|SHIFT_FLAG
+ b"\x8d" # J x0d|SHIFT_FLAG
+ b"\x8e" # K x0e|SHIFT_FLAG
+ b"\x8f" # L x0f|SHIFT_FLAG
+ b"\x90" # M x10|SHIFT_FLAG
+ b"\x91" # N x11|SHIFT_FLAG
+ b"\x92" # O x12|SHIFT_FLAG
+ b"\x93" # P x13|SHIFT_FLAG
+ b"\x94" # Q x14|SHIFT_FLAG
+ b"\x95" # R x15|SHIFT_FLAG
+ b"\x96" # S x16|SHIFT_FLAG
+ b"\x97" # T x17|SHIFT_FLAG
+ b"\x98" # U x18|SHIFT_FLAG
+ b"\x99" # V x19|SHIFT_FLAG
+ b"\x9a" # W x1a|SHIFT_FLAG
+ b"\x9b" # X x1b|SHIFT_FLAG
+ b"\x9c" # Y x1c|SHIFT_FLAG
+ b"\x9d" # Z x1d|SHIFT_FLAG
+ b"\x2f" # [
+ b"\x31" # \ backslash
+ b"\x30" # ]
+ b"\xa3" # ^ x23|SHIFT_FLAG (shift 6)
+ b"\xad" # _ x2d|SHIFT_FLAG (shift -)
+ b"\x35" # `
+ b"\x04" # a
+ b"\x05" # b
+ b"\x06" # c
+ b"\x07" # d
+ b"\x08" # e
+ b"\x09" # f
+ b"\x0a" # g
+ b"\x0b" # h
+ b"\x0c" # i
+ b"\x0d" # j
+ b"\x0e" # k
+ b"\x0f" # l
+ b"\x10" # m
+ b"\x11" # n
+ b"\x12" # o
+ b"\x13" # p
+ b"\x14" # q
+ b"\x15" # r
+ b"\x16" # s
+ b"\x17" # t
+ b"\x18" # u
+ b"\x19" # v
+ b"\x1a" # w
+ b"\x1b" # x
+ b"\x1c" # y
+ b"\x1d" # z
+ b"\xaf" # { x2f|SHIFT_FLAG (shift [)
+ b"\xb1" # | x31|SHIFT_FLAG (shift \)
+ b"\xb0" # } x30|SHIFT_FLAG (shift ])
+ b"\xb5" # ~ x35|SHIFT_FLAG (shift `)
+ b"\x4c" # DEL DELETE (called Forward Delete in usb.org document)
+ )
+
+
+KeyboardLayout = KeyboardLayoutUS
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keycode.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keycode.py
new file mode 100644
index 0000000..14c8aa1
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/keycode.py
@@ -0,0 +1,312 @@
+# SPDX-FileCopyrightText: 2017 Scott Shawcroft for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.keycode.Keycode`
+====================================================
+
+* Author(s): Scott Shawcroft, Dan Halbert
+"""
+
+try:
+ import typing # pylint: disable=unused-import
+except ImportError:
+ pass
+
+
+class Keycode:
+ """USB HID Keycode constants.
+
+ This list is modeled after the names for USB keycodes defined in
+ https://usb.org/sites/default/files/hut1_21_0.pdf#page=83.
+ This list does not include every single code, but does include all the keys on
+ a regular PC or Mac keyboard.
+
+ Remember that keycodes are the names for key *positions* on a US keyboard, and may
+ not correspond to the character that you mean to send if you want to emulate non-US keyboard.
+ For instance, on a French keyboard (AZERTY instead of QWERTY),
+ the keycode for 'q' is used to indicate an 'a'. Likewise, 'y' represents 'z' on
+ a German keyboard. This is historical: the idea was that the keycaps could be changed
+ without changing the keycodes sent, so that different firmware was not needed for
+ different variations of a keyboard.
+ """
+
+ # pylint: disable-msg=invalid-name
+ A = 0x04
+ """``a`` and ``A``"""
+ B = 0x05
+ """``b`` and ``B``"""
+ C = 0x06
+ """``c`` and ``C``"""
+ D = 0x07
+ """``d`` and ``D``"""
+ E = 0x08
+ """``e`` and ``E``"""
+ F = 0x09
+ """``f`` and ``F``"""
+ G = 0x0A
+ """``g`` and ``G``"""
+ H = 0x0B
+ """``h`` and ``H``"""
+ I = 0x0C
+ """``i`` and ``I``"""
+ J = 0x0D
+ """``j`` and ``J``"""
+ K = 0x0E
+ """``k`` and ``K``"""
+ L = 0x0F
+ """``l`` and ``L``"""
+ M = 0x10
+ """``m`` and ``M``"""
+ N = 0x11
+ """``n`` and ``N``"""
+ O = 0x12
+ """``o`` and ``O``"""
+ P = 0x13
+ """``p`` and ``P``"""
+ Q = 0x14
+ """``q`` and ``Q``"""
+ R = 0x15
+ """``r`` and ``R``"""
+ S = 0x16
+ """``s`` and ``S``"""
+ T = 0x17
+ """``t`` and ``T``"""
+ U = 0x18
+ """``u`` and ``U``"""
+ V = 0x19
+ """``v`` and ``V``"""
+ W = 0x1A
+ """``w`` and ``W``"""
+ X = 0x1B
+ """``x`` and ``X``"""
+ Y = 0x1C
+ """``y`` and ``Y``"""
+ Z = 0x1D
+ """``z`` and ``Z``"""
+
+ ONE = 0x1E
+ """``1`` and ``!``"""
+ TWO = 0x1F
+ """``2`` and ``@``"""
+ THREE = 0x20
+ """``3`` and ``#``"""
+ FOUR = 0x21
+ """``4`` and ``$``"""
+ FIVE = 0x22
+ """``5`` and ``%``"""
+ SIX = 0x23
+ """``6`` and ``^``"""
+ SEVEN = 0x24
+ """``7`` and ``&``"""
+ EIGHT = 0x25
+ """``8`` and ``*``"""
+ NINE = 0x26
+ """``9`` and ``(``"""
+ ZERO = 0x27
+ """``0`` and ``)``"""
+ ENTER = 0x28
+ """Enter (Return)"""
+ RETURN = ENTER
+ """Alias for ``ENTER``"""
+ ESCAPE = 0x29
+ """Escape"""
+ BACKSPACE = 0x2A
+ """Delete backward (Backspace)"""
+ TAB = 0x2B
+ """Tab and Backtab"""
+ SPACEBAR = 0x2C
+ """Spacebar"""
+ SPACE = SPACEBAR
+ """Alias for SPACEBAR"""
+ MINUS = 0x2D
+ """``-` and ``_``"""
+ EQUALS = 0x2E
+ """``=` and ``+``"""
+ LEFT_BRACKET = 0x2F
+ """``[`` and ``{``"""
+ RIGHT_BRACKET = 0x30
+ """``]`` and ``}``"""
+ BACKSLASH = 0x31
+ r"""``\`` and ``|``"""
+ POUND = 0x32
+ """``#`` and ``~`` (Non-US keyboard)"""
+ SEMICOLON = 0x33
+ """``;`` and ``:``"""
+ QUOTE = 0x34
+ """``'`` and ``"``"""
+ GRAVE_ACCENT = 0x35
+ r""":literal:`\`` and ``~``"""
+ COMMA = 0x36
+ """``,`` and ``<``"""
+ PERIOD = 0x37
+ """``.`` and ``>``"""
+ FORWARD_SLASH = 0x38
+ """``/`` and ``?``"""
+
+ CAPS_LOCK = 0x39
+ """Caps Lock"""
+
+ F1 = 0x3A
+ """Function key F1"""
+ F2 = 0x3B
+ """Function key F2"""
+ F3 = 0x3C
+ """Function key F3"""
+ F4 = 0x3D
+ """Function key F4"""
+ F5 = 0x3E
+ """Function key F5"""
+ F6 = 0x3F
+ """Function key F6"""
+ F7 = 0x40
+ """Function key F7"""
+ F8 = 0x41
+ """Function key F8"""
+ F9 = 0x42
+ """Function key F9"""
+ F10 = 0x43
+ """Function key F10"""
+ F11 = 0x44
+ """Function key F11"""
+ F12 = 0x45
+ """Function key F12"""
+
+ PRINT_SCREEN = 0x46
+ """Print Screen (SysRq)"""
+ SCROLL_LOCK = 0x47
+ """Scroll Lock"""
+ PAUSE = 0x48
+ """Pause (Break)"""
+
+ INSERT = 0x49
+ """Insert"""
+ HOME = 0x4A
+ """Home (often moves to beginning of line)"""
+ PAGE_UP = 0x4B
+ """Go back one page"""
+ DELETE = 0x4C
+ """Delete forward"""
+ END = 0x4D
+ """End (often moves to end of line)"""
+ PAGE_DOWN = 0x4E
+ """Go forward one page"""
+
+ RIGHT_ARROW = 0x4F
+ """Move the cursor right"""
+ LEFT_ARROW = 0x50
+ """Move the cursor left"""
+ DOWN_ARROW = 0x51
+ """Move the cursor down"""
+ UP_ARROW = 0x52
+ """Move the cursor up"""
+
+ KEYPAD_NUMLOCK = 0x53
+ """Num Lock (Clear on Mac)"""
+ KEYPAD_FORWARD_SLASH = 0x54
+ """Keypad ``/``"""
+ KEYPAD_ASTERISK = 0x55
+ """Keypad ``*``"""
+ KEYPAD_MINUS = 0x56
+ """Keyapd ``-``"""
+ KEYPAD_PLUS = 0x57
+ """Keypad ``+``"""
+ KEYPAD_ENTER = 0x58
+ """Keypad Enter"""
+ KEYPAD_ONE = 0x59
+ """Keypad ``1`` and End"""
+ KEYPAD_TWO = 0x5A
+ """Keypad ``2`` and Down Arrow"""
+ KEYPAD_THREE = 0x5B
+ """Keypad ``3`` and PgDn"""
+ KEYPAD_FOUR = 0x5C
+ """Keypad ``4`` and Left Arrow"""
+ KEYPAD_FIVE = 0x5D
+ """Keypad ``5``"""
+ KEYPAD_SIX = 0x5E
+ """Keypad ``6`` and Right Arrow"""
+ KEYPAD_SEVEN = 0x5F
+ """Keypad ``7`` and Home"""
+ KEYPAD_EIGHT = 0x60
+ """Keypad ``8`` and Up Arrow"""
+ KEYPAD_NINE = 0x61
+ """Keypad ``9`` and PgUp"""
+ KEYPAD_ZERO = 0x62
+ """Keypad ``0`` and Ins"""
+ KEYPAD_PERIOD = 0x63
+ """Keypad ``.`` and Del"""
+ KEYPAD_BACKSLASH = 0x64
+ """Keypad ``\\`` and ``|`` (Non-US)"""
+
+ APPLICATION = 0x65
+ """Application: also known as the Menu key (Windows)"""
+ POWER = 0x66
+ """Power (Mac)"""
+ KEYPAD_EQUALS = 0x67
+ """Keypad ``=`` (Mac)"""
+ F13 = 0x68
+ """Function key F13 (Mac)"""
+ F14 = 0x69
+ """Function key F14 (Mac)"""
+ F15 = 0x6A
+ """Function key F15 (Mac)"""
+ F16 = 0x6B
+ """Function key F16 (Mac)"""
+ F17 = 0x6C
+ """Function key F17 (Mac)"""
+ F18 = 0x6D
+ """Function key F18 (Mac)"""
+ F19 = 0x6E
+ """Function key F19 (Mac)"""
+
+ F20 = 0x6F
+ """Function key F20"""
+ F21 = 0x70
+ """Function key F21"""
+ F22 = 0x71
+ """Function key F22"""
+ F23 = 0x72
+ """Function key F23"""
+ F24 = 0x73
+ """Function key F24"""
+
+ LEFT_CONTROL = 0xE0
+ """Control modifier left of the spacebar"""
+ CONTROL = LEFT_CONTROL
+ """Alias for LEFT_CONTROL"""
+ LEFT_SHIFT = 0xE1
+ """Shift modifier left of the spacebar"""
+ SHIFT = LEFT_SHIFT
+ """Alias for LEFT_SHIFT"""
+ LEFT_ALT = 0xE2
+ """Alt modifier left of the spacebar"""
+ ALT = LEFT_ALT
+ """Alias for LEFT_ALT; Alt is also known as Option (Mac)"""
+ OPTION = ALT
+ """Labeled as Option on some Mac keyboards"""
+ LEFT_GUI = 0xE3
+ """GUI modifier left of the spacebar"""
+ GUI = LEFT_GUI
+ """Alias for LEFT_GUI; GUI is also known as the Windows key, Command (Mac), or Meta"""
+ WINDOWS = GUI
+ """Labeled with a Windows logo on Windows keyboards"""
+ COMMAND = GUI
+ """Labeled as Command on Mac keyboards, with a clover glyph"""
+ RIGHT_CONTROL = 0xE4
+ """Control modifier right of the spacebar"""
+ RIGHT_SHIFT = 0xE5
+ """Shift modifier right of the spacebar"""
+ RIGHT_ALT = 0xE6
+ """Alt modifier right of the spacebar"""
+ RIGHT_GUI = 0xE7
+ """GUI modifier right of the spacebar"""
+
+ # pylint: enable-msg=invalid-name
+ @classmethod
+ def modifier_bit(cls, keycode: int) -> int:
+ """Return the modifer bit to be set in an HID keycode report if this is a
+ modifier key; otherwise return 0."""
+ return (
+ 1 << (keycode - 0xE0) if cls.LEFT_CONTROL <= keycode <= cls.RIGHT_GUI else 0
+ )
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/mouse.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/mouse.py
new file mode 100644
index 0000000..3b324db
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/adafruit_hid/mouse.py
@@ -0,0 +1,152 @@
+# SPDX-FileCopyrightText: 2017 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`adafruit_hid.mouse.Mouse`
+====================================================
+
+* Author(s): Dan Halbert
+"""
+import time
+
+from . import find_device
+
+try:
+ from typing import Sequence
+ import usb_hid
+except ImportError:
+ pass
+
+
+class Mouse:
+ """Send USB HID mouse reports."""
+
+ LEFT_BUTTON = 1
+ """Left mouse button."""
+ RIGHT_BUTTON = 2
+ """Right mouse button."""
+ MIDDLE_BUTTON = 4
+ """Middle mouse button."""
+
+ def __init__(self, devices: Sequence[usb_hid.Device]):
+ """Create a Mouse object that will send USB mouse HID reports.
+
+ Devices can be a sequence of devices that includes a keyboard device or a keyboard device
+ itself. A device is any object that implements ``send_report()``, ``usage_page`` and
+ ``usage``.
+ """
+ self._mouse_device = find_device(devices, usage_page=0x1, usage=0x02)
+
+ # Reuse this bytearray to send mouse reports.
+ # report[0] buttons pressed (LEFT, MIDDLE, RIGHT)
+ # report[1] x movement
+ # report[2] y movement
+ # 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._send_no_move()
+ except OSError:
+ time.sleep(1)
+ self._send_no_move()
+
+ def press(self, buttons: int) -> None:
+ """Press the given mouse buttons.
+
+ :param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
+ ``MIDDLE_BUTTON``, and ``RIGHT_BUTTON``.
+
+ Examples::
+
+ # Press the left button.
+ m.press(Mouse.LEFT_BUTTON)
+
+ # Press the left and right buttons simultaneously.
+ m.press(Mouse.LEFT_BUTTON | Mouse.RIGHT_BUTTON)
+ """
+ self.report[0] |= buttons
+ self._send_no_move()
+
+ def release(self, buttons: int) -> None:
+ """Release the given mouse buttons.
+
+ :param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
+ ``MIDDLE_BUTTON``, and ``RIGHT_BUTTON``.
+ """
+ self.report[0] &= ~buttons
+ self._send_no_move()
+
+ def release_all(self) -> None:
+ """Release all the mouse buttons."""
+ self.report[0] = 0
+ self._send_no_move()
+
+ def click(self, buttons: int) -> None:
+ """Press and release the given mouse buttons.
+
+ :param buttons: a bitwise-or'd combination of ``LEFT_BUTTON``,
+ ``MIDDLE_BUTTON``, and ``RIGHT_BUTTON``.
+
+ Examples::
+
+ # Click the left button.
+ m.click(Mouse.LEFT_BUTTON)
+
+ # Double-click the left button.
+ m.click(Mouse.LEFT_BUTTON)
+ m.click(Mouse.LEFT_BUTTON)
+ """
+ self.press(buttons)
+ self.release(buttons)
+
+ def move(self, x: int = 0, y: int = 0, wheel: int = 0) -> None:
+ """Move the mouse and turn the wheel as directed.
+
+ :param x: Move the mouse along the x axis. Negative is to the left, positive
+ is to the right.
+ :param y: Move the mouse along the y axis. Negative is upwards on the display,
+ 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.
+
+ Examples::
+
+ # Move 100 to the left. Do not move up and down. Do not roll the scroll wheel.
+ m.move(-100, 0, 0)
+ # Same, with keyword arguments.
+ m.move(x=-100)
+
+ # Move diagonally to the upper right.
+ m.move(50, 20)
+ # Same.
+ m.move(x=50, y=-20)
+
+ # Roll the mouse wheel away from the user.
+ m.move(wheel=1)
+ """
+ # 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 & 0xFF
+ self.report[2] = partial_y & 0xFF
+ self.report[3] = partial_wheel & 0xFF
+ self._mouse_device.send_report(self.report)
+ x -= partial_x
+ y -= partial_y
+ wheel -= partial_wheel
+
+ def _send_no_move(self) -> None:
+ """Send a button-only report."""
+ self.report[1] = 0
+ self.report[2] = 0
+ self.report[3] = 0
+ self._mouse_device.send_report(self.report)
+
+ @staticmethod
+ def _limit(dist: int) -> int:
+ return min(127, max(-127, dist))
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico
new file mode 100644
index 0000000..5aca983
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico
Binary files differ
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico.license b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico.license
new file mode 100644
index 0000000..86a3fbf
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/_static/favicon.ico.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: 2018 Phillip Torrone for Adafruit Industries
+
+SPDX-License-Identifier: CC-BY-4.0
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst
new file mode 100644
index 0000000..03b92bc
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst
@@ -0,0 +1,23 @@
+
+.. If you created a package, create one automodule per module in the package.
+
+.. automodule:: adafruit_hid.keyboard
+ :members:
+
+.. automodule:: adafruit_hid.keycode
+ :members:
+
+.. automodule:: adafruit_hid.keyboard_layout_us
+ :members:
+
+.. automodule:: adafruit_hid.keyboard_layout_base
+ :members:
+
+.. automodule:: adafruit_hid.mouse
+ :members:
+
+.. automodule:: adafruit_hid.consumer_control
+ :members:
+
+.. automodule:: adafruit_hid.consumer_control_code
+ :members:
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst.license b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst.license
new file mode 100644
index 0000000..9aae48d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/api.rst.license
@@ -0,0 +1,3 @@
+# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/conf.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/conf.py
new file mode 100644
index 0000000..c35d131
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/conf.py
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+import os
+import sys
+
+sys.path.insert(0, os.path.abspath(".."))
+
+# -- General configuration ------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ "sphinx.ext.autodoc",
+ "sphinx.ext.intersphinx",
+ "sphinx.ext.viewcode",
+]
+
+intersphinx_mapping = {
+ "python": ("https://docs.python.org/3", None),
+ "CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
+}
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ["_templates"]
+
+source_suffix = ".rst"
+
+# The master toctree document.
+master_doc = "index"
+
+# General information about the project.
+project = "Adafruit HID Library"
+copyright = "2017 Scott Shawcroft"
+author = "Scott Shawcroft"
+
+# Ignore imports of these modules, which sphinx will not know about.
+autodoc_mock_imports = ["usb_hid"]
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = "1.0"
+# The full version, including alpha/beta/rc tags.
+release = "1.0"
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This patterns also effect to html_static_path and html_extra_path
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
+
+# The reST default role (used for this markup: `text`) to use for all
+# documents.
+#
+default_role = "any"
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#
+add_function_parentheses = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = "sphinx"
+
+# If true, `todo` and `todoList` produce output, else they produce nothing.
+todo_include_todos = False
+
+# If this is True, todo emits a warning for each TODO entries. The default is False.
+todo_emit_warnings = True
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+on_rtd = os.environ.get("READTHEDOCS", None) == "True"
+
+if not on_rtd: # only import and set the theme if we're building docs locally
+ try:
+ import sphinx_rtd_theme
+
+ html_theme = "sphinx_rtd_theme"
+ html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
+ except:
+ html_theme = "default"
+ html_theme_path = ["."]
+else:
+ html_theme_path = ["."]
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ["_static"]
+
+# The name of an image file (relative to this directory) to use as a favicon of
+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#
+html_favicon = "_static/favicon.ico"
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = "AdafruitHIDLibrarydoc"
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ (
+ master_doc,
+ "AdafruitHIDLibrary.tex",
+ "Adafruit HID Library Documentation",
+ "Scott Shawcroft",
+ "manual",
+ ),
+]
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (
+ master_doc,
+ "adafruitHIDlibrary",
+ "Adafruit HID Library Documentation",
+ [author],
+ 1,
+ )
+]
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (
+ master_doc,
+ "AdafruitHIDLibrary",
+ "Adafruit HID Library Documentation",
+ author,
+ "AdafruitHIDLibrary",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
+]
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst
new file mode 100644
index 0000000..549b4bb
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst
@@ -0,0 +1,44 @@
+Simple test
+------------
+
+Ensure your device works with this simple test.
+
+.. literalinclude:: ../examples/hid_simpletest.py
+ :caption: examples/hid_simpletest.py
+ :linenos:
+
+Keyboard Shortcuts
+-------------------
+
+Send ALT+Tab for swapping windows, and CTRL+K for searching in a browser.
+
+.. literalinclude:: ../examples/hid_keyboard_shortcuts.py
+ :caption: examples/hid_keyboard_shortcuts.py
+ :linenos:
+
+Simple Gamepad
+---------------
+
+Send gamepad buttons and joystick to the host.
+
+.. literalinclude:: ../examples/hid_simple_gamepad.py
+ :caption: examples/hid_simple_gamepad.py
+ :linenos:
+
+HID Joywing
+------------
+
+Use Joy FeatherWing to drive Gamepad.
+
+.. literalinclude:: ../examples/hid_joywing_gamepad.py
+ :caption: examples/hid_joywing_gamepad.py
+ :linenos:
+
+Consumer Control Brightness
+----------------------------
+
+Send brightness up and down consumer codes to the host.
+
+.. literalinclude:: ../examples/hid_consumer_control_brightness.py
+ :caption: examples/hid_consumer_control_brightness.py
+ :linenos:
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst.license b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst.license
new file mode 100644
index 0000000..9aae48d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/examples.rst.license
@@ -0,0 +1,3 @@
+# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst
new file mode 100644
index 0000000..5ddac8b
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst
@@ -0,0 +1,45 @@
+.. include:: ../README.rst
+
+Table of Contents
+=================
+
+.. toctree::
+ :maxdepth: 4
+ :hidden:
+
+ self
+
+.. toctree::
+ :caption: Examples
+
+ examples
+
+.. toctree::
+ :caption: API Reference
+ :maxdepth: 3
+
+ api
+
+.. toctree::
+ :caption: Tutorials
+
+.. toctree::
+ :caption: Related Products
+
+.. toctree::
+ :caption: Other Links
+
+ Download <https://github.com/adafruit/Adafruit_CircuitPython_HID/releases/latest>
+ CircuitPython Reference Documentation <https://docs.circuitpython.org>
+ CircuitPython Support Forum <https://forums.adafruit.com/viewforum.php?f=60>
+ Discord Chat <https://adafru.it/discord>
+ Adafruit Learning System <https://learn.adafruit.com>
+ Adafruit Blog <https://blog.adafruit.com>
+ Adafruit Store <https://www.adafruit.com>
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst.license b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst.license
new file mode 100644
index 0000000..9aae48d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/index.rst.license
@@ -0,0 +1,3 @@
+# SPDX-FileCopyrightText: 2020 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/requirements.txt b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/requirements.txt
new file mode 100644
index 0000000..88e6733
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/docs/requirements.txt
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
+#
+# SPDX-License-Identifier: Unlicense
+
+sphinx>=4.0.0
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_consumer_control_brightness.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_consumer_control_brightness.py
new file mode 100644
index 0000000..1cf922c
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_consumer_control_brightness.py
@@ -0,0 +1,32 @@
+# SPDX-FileCopyrightText: 2021 Tim C for Adafruit Industries
+# SPDX-License-Identifier: MIT
+
+import time
+import board
+import digitalio
+import usb_hid
+from adafruit_hid.consumer_control import ConsumerControl
+from adafruit_hid.consumer_control_code import ConsumerControlCode
+
+cc = ConsumerControl(usb_hid.devices)
+
+# define buttons. these can be any physical switches/buttons, but the values
+# here work out-of-the-box with a FunHouse UP and DOWN buttons.
+button_up = digitalio.DigitalInOut(board.BUTTON_UP)
+button_up.switch_to_input(pull=digitalio.Pull.DOWN)
+
+button_down = digitalio.DigitalInOut(board.BUTTON_DOWN)
+button_down.switch_to_input(pull=digitalio.Pull.DOWN)
+
+while True:
+ if button_up.value:
+ print("Button up pressed!")
+ # send brightness up button press
+ cc.send(ConsumerControlCode.BRIGHTNESS_INCREMENT)
+
+ if button_down.value:
+ print("Button down pressed!")
+ # send brightness down button press
+ cc.send(ConsumerControlCode.BRIGHTNESS_DECREMENT)
+
+ time.sleep(0.1)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_gamepad.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_gamepad.py
new file mode 100644
index 0000000..01a9653
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_gamepad.py
@@ -0,0 +1,157 @@
+# SPDX-FileCopyrightText: 2018 Dan Halbert for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""
+`Gamepad`
+====================================================
+
+* Author(s): Dan Halbert
+"""
+
+import struct
+import time
+
+from adafruit_hid import find_device
+
+
+class Gamepad:
+ """Emulate a generic gamepad controller with 16 buttons,
+ numbered 1-16, and two joysticks, one controlling
+ ``x` and ``y`` values, and the other controlling ``z`` and
+ ``r_z`` (z rotation or ``Rz``) values.
+
+ The joystick values could be interpreted
+ differently by the receiving program: those are just the names used here.
+ The joystick values are in the range -127 to 127."""
+
+ def __init__(self, devices):
+ """Create a Gamepad object that will send USB gamepad HID reports.
+
+ Devices can be a list of devices that includes a gamepad device or a gamepad device
+ itself. A device is any object that implements ``send_report()``, ``usage_page`` and
+ ``usage``.
+ """
+ self._gamepad_device = find_device(devices, usage_page=0x1, usage=0x05)
+
+ # Reuse this bytearray to send mouse reports.
+ # Typically controllers start numbering buttons at 1 rather than 0.
+ # report[0] buttons 1-8 (LSB is button 1)
+ # report[1] buttons 9-16
+ # report[2] joystick 0 x: -127 to 127
+ # report[3] joystick 0 y: -127 to 127
+ # report[4] joystick 1 x: -127 to 127
+ # report[5] joystick 1 y: -127 to 127
+ self._report = bytearray(6)
+
+ # Remember the last report as well, so we can avoid sending
+ # duplicate reports.
+ self._last_report = bytearray(6)
+
+ # Store settings separately before putting into report. Saves code
+ # especially for buttons.
+ self._buttons_state = 0
+ self._joy_x = 0
+ self._joy_y = 0
+ self._joy_z = 0
+ self._joy_r_z = 0
+
+ # Send an initial report to test if HID device is ready.
+ # If not, wait a bit and try once more.
+ try:
+ self.reset_all()
+ except OSError:
+ time.sleep(1)
+ self.reset_all()
+
+ def press_buttons(self, *buttons):
+ """Press and hold the given buttons."""
+ for button in buttons:
+ self._buttons_state |= 1 << self._validate_button_number(button) - 1
+ self._send()
+
+ def release_buttons(self, *buttons):
+ """Release the given buttons."""
+ for button in buttons:
+ self._buttons_state &= ~(1 << self._validate_button_number(button) - 1)
+ self._send()
+
+ def release_all_buttons(self):
+ """Release all the buttons."""
+
+ self._buttons_state = 0
+ self._send()
+
+ def click_buttons(self, *buttons):
+ """Press and release the given buttons."""
+ self.press_buttons(*buttons)
+ self.release_buttons(*buttons)
+
+ def move_joysticks(self, x=None, y=None, z=None, r_z=None):
+ """Set and send the given joystick values.
+ The joysticks will remain set with the given values until changed
+
+ One joystick provides ``x`` and ``y`` values,
+ and the other provides ``z`` and ``r_z`` (z rotation).
+ Any values left as ``None`` will not be changed.
+
+ All values must be in the range -127 to 127 inclusive.
+
+ Examples::
+
+ # Change x and y values only.
+ gp.move_joysticks(x=100, y=-50)
+
+ # Reset all joystick values to center position.
+ gp.move_joysticks(0, 0, 0, 0)
+ """
+ if x is not None:
+ self._joy_x = self._validate_joystick_value(x)
+ if y is not None:
+ self._joy_y = self._validate_joystick_value(y)
+ if z is not None:
+ self._joy_z = self._validate_joystick_value(z)
+ if r_z is not None:
+ self._joy_r_z = self._validate_joystick_value(r_z)
+ self._send()
+
+ def reset_all(self):
+ """Release all buttons and set joysticks to zero."""
+ self._buttons_state = 0
+ self._joy_x = 0
+ self._joy_y = 0
+ self._joy_z = 0
+ self._joy_r_z = 0
+ self._send(always=True)
+
+ def _send(self, always=False):
+ """Send a report with all the existing settings.
+ If ``always`` is ``False`` (the default), send only if there have been changes.
+ """
+ struct.pack_into(
+ "<Hbbbb",
+ self._report,
+ 0,
+ self._buttons_state,
+ self._joy_x,
+ self._joy_y,
+ self._joy_z,
+ self._joy_r_z,
+ )
+
+ if always or self._last_report != self._report:
+ self._gamepad_device.send_report(self._report)
+ # Remember what we sent, without allocating new storage.
+ self._last_report[:] = self._report
+
+ @staticmethod
+ def _validate_button_number(button):
+ if not 1 <= button <= 16:
+ raise ValueError("Button number must in range 1 to 16")
+ return button
+
+ @staticmethod
+ def _validate_joystick_value(value):
+ if not -127 <= value <= 127:
+ raise ValueError("Joystick value must be in range -127 to 127")
+ return value
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_joywing_gamepad.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_joywing_gamepad.py
new file mode 100644
index 0000000..2473675
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_joywing_gamepad.py
@@ -0,0 +1,76 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+# SPDX-License-Identifier: MIT
+
+# Use Joy FeatherWing to drive Gamepad.
+# https://www.adafruit.com/product/3632
+# https://learn.adafruit.com/joy-featherwing
+
+# You must add a gamepad HID device inside your boot.py file
+# in order to use this example.
+# See this Learn Guide for details:
+# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/hid-devices#custom-hid-devices-3096614-9
+
+import time
+
+import board
+import busio
+from micropython import const
+from adafruit_seesaw.seesaw import Seesaw
+import usb_hid
+from hid_gamepad import Gamepad
+
+
+def range_map(value, in_min, in_max, out_min, out_max):
+ return (value - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
+
+
+BUTTON_RIGHT = const(6)
+BUTTON_DOWN = const(7)
+BUTTON_LEFT = const(9)
+BUTTON_UP = const(10)
+BUTTON_SEL = const(14)
+button_mask = const(
+ (1 << BUTTON_RIGHT)
+ | (1 << BUTTON_DOWN)
+ | (1 << BUTTON_LEFT)
+ | (1 << BUTTON_UP)
+ | (1 << BUTTON_SEL)
+)
+
+i2c = busio.I2C(board.SCL, board.SDA)
+
+ss = Seesaw(i2c)
+
+ss.pin_mode_bulk(button_mask, ss.INPUT_PULLUP)
+
+last_game_x = 0
+last_game_y = 0
+
+g = Gamepad(usb_hid.devices)
+
+while True:
+ x = ss.analog_read(2)
+ y = ss.analog_read(3)
+
+ game_x = range_map(x, 0, 1023, -127, 127)
+ game_y = range_map(y, 0, 1023, -127, 127)
+ if last_game_x != game_x or last_game_y != game_y:
+ last_game_x = game_x
+ last_game_y = game_y
+ print(game_x, game_y)
+ g.move_joysticks(x=game_x, y=game_y)
+
+ buttons = (BUTTON_RIGHT, BUTTON_DOWN, BUTTON_LEFT, BUTTON_UP, BUTTON_SEL)
+ button_state = [False] * len(buttons)
+ for i, button in enumerate(buttons):
+ buttons = ss.digital_read_bulk(button_mask)
+ if not (buttons & (1 << button) and not button_state[i]):
+ g.press_buttons(i + 1)
+ print("Press", i + 1)
+ button_state[i] = True
+ elif button_state[i]:
+ g.release_buttons(i + 1)
+ print("Release", i + 1)
+ button_state[i] = False
+
+ time.sleep(0.01)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_keyboard_shortcuts.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_keyboard_shortcuts.py
new file mode 100644
index 0000000..8a25bd5
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_keyboard_shortcuts.py
@@ -0,0 +1,32 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+# SPDX-License-Identifier: MIT
+
+import time
+import board
+import digitalio
+import usb_hid
+from adafruit_hid.keyboard import Keyboard
+from adafruit_hid.keycode import Keycode
+
+kbd = Keyboard(usb_hid.devices)
+
+# define buttons. these can be any physical switches/buttons, but the values
+# here work out-of-the-box with a CircuitPlayground Express' A and B buttons.
+swap = digitalio.DigitalInOut(board.D4)
+swap.direction = digitalio.Direction.INPUT
+swap.pull = digitalio.Pull.DOWN
+
+search = digitalio.DigitalInOut(board.D5)
+search.direction = digitalio.Direction.INPUT
+search.pull = digitalio.Pull.DOWN
+
+while True:
+ # press ALT+TAB to swap windows
+ if swap.value:
+ kbd.send(Keycode.ALT, Keycode.TAB)
+
+ # press CTRL+K, which in a web browser will open the search dialog
+ elif search.value:
+ kbd.send(Keycode.CONTROL, Keycode.K)
+
+ time.sleep(0.1)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simple_gamepad.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simple_gamepad.py
new file mode 100644
index 0000000..614cc84
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simple_gamepad.py
@@ -0,0 +1,57 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+# SPDX-License-Identifier: MIT
+
+# You must add a gamepad HID device inside your boot.py file
+# in order to use this example.
+# See this Learn Guide for details:
+# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/hid-devices#custom-hid-devices-3096614-9
+
+import board
+import digitalio
+import analogio
+import usb_hid
+
+from hid_gamepad import Gamepad
+
+gp = Gamepad(usb_hid.devices)
+
+# Create some buttons. The physical buttons are connected
+# to ground on one side and these and these pins on the other.
+button_pins = (board.D2, board.D3, board.D4, board.D5)
+
+# Map the buttons to button numbers on the Gamepad.
+# gamepad_buttons[i] will send that button number when buttons[i]
+# is pushed.
+gamepad_buttons = (1, 2, 8, 15)
+
+buttons = [digitalio.DigitalInOut(pin) for pin in button_pins]
+for button in buttons:
+ button.direction = digitalio.Direction.INPUT
+ button.pull = digitalio.Pull.UP
+
+# Connect an analog two-axis joystick to A4 and A5.
+ax = analogio.AnalogIn(board.A4)
+ay = analogio.AnalogIn(board.A5)
+
+# Equivalent of Arduino's map() function.
+def range_map(x, in_min, in_max, out_min, out_max):
+ return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
+
+
+while True:
+ # Buttons are grounded when pressed (.value = False).
+ for i, button in enumerate(buttons):
+ gamepad_button_num = gamepad_buttons[i]
+ if button.value:
+ gp.release_buttons(gamepad_button_num)
+ print(" release", gamepad_button_num, end="")
+ else:
+ gp.press_buttons(gamepad_button_num)
+ print(" press", gamepad_button_num, end="")
+
+ # Convert range[0, 65535] to -127 to 127
+ gp.move_joysticks(
+ x=range_map(ax.value, 0, 65535, -127, 127),
+ y=range_map(ay.value, 0, 65535, -127, 127),
+ )
+ print(" x", ax.value, "y", ay.value)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simpletest.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simpletest.py
new file mode 100644
index 0000000..3c5f651
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/examples/hid_simpletest.py
@@ -0,0 +1,31 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+# SPDX-License-Identifier: MIT
+
+import time
+import board
+import digitalio
+import usb_hid
+from adafruit_hid.mouse import Mouse
+
+mouse = Mouse(usb_hid.devices)
+
+# define buttons. these can be any physical switches/buttons, but the values
+# here work out-of-the-box with a CircuitPlayground Express' A and B buttons.
+up = digitalio.DigitalInOut(board.D4)
+up.direction = digitalio.Direction.INPUT
+up.pull = digitalio.Pull.DOWN
+
+down = digitalio.DigitalInOut(board.D5)
+down.direction = digitalio.Direction.INPUT
+down.pull = digitalio.Pull.DOWN
+
+while True:
+ # scroll up one unit (varies with host/OS)
+ if up.value:
+ mouse.move(wheel=1)
+
+ # scroll down one unit (varies with host/OS)
+ elif down.value:
+ mouse.move(wheel=-1)
+
+ time.sleep(0.1)
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/requirements.txt b/circuitpython/frozen/Adafruit_CircuitPython_HID/requirements.txt
new file mode 100644
index 0000000..17a850d
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/requirements.txt
@@ -0,0 +1,5 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: Unlicense
+
+Adafruit-Blinka
diff --git a/circuitpython/frozen/Adafruit_CircuitPython_HID/setup.py b/circuitpython/frozen/Adafruit_CircuitPython_HID/setup.py
new file mode 100644
index 0000000..3fb2a36
--- /dev/null
+++ b/circuitpython/frozen/Adafruit_CircuitPython_HID/setup.py
@@ -0,0 +1,55 @@
+# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+
+"""A setuptools based setup module.
+
+See:
+https://packaging.python.org/en/latest/distributing.html
+https://github.com/pypa/sampleproject
+"""
+
+# Always prefer setuptools over distutils
+from setuptools import setup, find_packages
+
+# To use a consistent encoding
+from codecs import open
+from os import path
+
+here = path.abspath(path.dirname(__file__))
+
+# Get the long description from the README file
+with open(path.join(here, "README.rst"), encoding="utf-8") as f:
+ long_description = f.read()
+
+setup(
+ name="adafruit-circuitpython-hid",
+ use_scm_version=True,
+ setup_requires=["setuptools_scm"],
+ description="CircuitPython helper library for simulating HID devices.",
+ long_description=long_description,
+ long_description_content_type="text/x-rst",
+ # The project's main homepage.
+ url="https://github.com/adafruit/Adafruit_CircuitPython_HID",
+ # Author details
+ author="Adafruit Industries",
+ author_email="circuitpython@adafruit.com",
+ install_requires=["Adafruit-Blinka"],
+ # Choose your license
+ license="MIT",
+ # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
+ classifiers=[
+ "Development Status :: 3 - Alpha",
+ "Intended Audience :: Developers",
+ "Topic :: Software Development :: Libraries",
+ "Topic :: System :: Hardware",
+ "License :: OSI Approved :: MIT License",
+ "Programming Language :: Python :: 3",
+ ],
+ # What does your project relate to?
+ keywords="adafruit hid human interface device keyboard mouse keycode keypad"
+ "hardware micropython circuitpython",
+ # You can just specify the packages manually here if your project is
+ # simple. Or you can use find_packages().
+ packages=["adafruit_hid"],
+)