|
| 1 | +# SPDX-FileCopyrightText: 2023 Björn Bösel for Adafruit Industries |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +""" |
| 6 | +USB HID Keyboard Example for Raspberry Pi Zero (W) |
| 7 | +=================================================== |
| 8 | +
|
| 9 | +Demonstrates how to use Blinka's ``usb_hid`` module to turn a |
| 10 | +Raspberry Pi Zero into a USB HID keyboard. |
| 11 | +
|
| 12 | +Prerequisites |
| 13 | +------------- |
| 14 | +1. Enable the dwc2 overlay (once, then reboot):: |
| 15 | +
|
| 16 | + sudo bash -c "echo 'dtoverlay=dwc2' >> /boot/config.txt" |
| 17 | + sudo reboot |
| 18 | +
|
| 19 | +2. Load the libcomposite kernel module:: |
| 20 | +
|
| 21 | + sudo modprobe libcomposite |
| 22 | +
|
| 23 | + To make it persistent across reboots:: |
| 24 | +
|
| 25 | + sudo bash -c "echo 'libcomposite' >> /etc/modules" |
| 26 | +
|
| 27 | +3. Install the CircuitPython HID library:: |
| 28 | +
|
| 29 | + pip3 install adafruit-circuitpython-hid |
| 30 | +
|
| 31 | +Wiring |
| 32 | +------ |
| 33 | +- Wire a button between GP20 and GND (types Shift+A). |
| 34 | +- Wire a button between GP21 and GND (types "Hello World!"). |
| 35 | +- Wire an LED + 1k resistor between GP16 and GND. |
| 36 | +- Connect the Pi Zero to the host computer via USB. |
| 37 | +
|
| 38 | +Run with:: |
| 39 | +
|
| 40 | + sudo -E python3 usb_hid_keyboard.py |
| 41 | +
|
| 42 | +The ``-E`` flag preserves the user environment so pip-installed |
| 43 | +packages are found when running as root. |
| 44 | +""" |
| 45 | + |
| 46 | +import time |
| 47 | +import board |
| 48 | +import digitalio |
| 49 | +import usb_hid |
| 50 | +from adafruit_hid.keyboard import Keyboard |
| 51 | +from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS |
| 52 | +from adafruit_hid.keycode import Keycode |
| 53 | +from usb_hid import Device |
| 54 | + |
| 55 | +# Button pins (activate internal pull-ups) |
| 56 | +keypress_pins = [board.D20, board.D21] |
| 57 | + |
| 58 | +# What each button sends: a Keycode or a string |
| 59 | +keys_pressed = [Keycode.A, "Hello World!\n"] |
| 60 | +control_key = Keycode.SHIFT |
| 61 | + |
| 62 | +# Set up button inputs with pull-ups |
| 63 | +key_pin_array = [] |
| 64 | +for pin in keypress_pins: |
| 65 | + key_pin = digitalio.DigitalInOut(pin) |
| 66 | + key_pin.direction = digitalio.Direction.INPUT |
| 67 | + key_pin.pull = digitalio.Pull.UP |
| 68 | + key_pin_array.append(key_pin) |
| 69 | + |
| 70 | +# Set up LED output |
| 71 | +led = digitalio.DigitalInOut(board.D16) |
| 72 | +led.direction = digitalio.Direction.OUTPUT |
| 73 | + |
| 74 | +# Create the USB HID keyboard |
| 75 | +usb_hid.enable([Device.KEYBOARD], boot_device=0) |
| 76 | +keyboard = Keyboard(usb_hid.devices) |
| 77 | +keyboard_layout = KeyboardLayoutUS(keyboard) |
| 78 | + |
| 79 | +print("Waiting for key press...") |
| 80 | + |
| 81 | +while True: |
| 82 | + for key_pin in key_pin_array: |
| 83 | + if not key_pin.value: # Button pressed (grounded) |
| 84 | + i = key_pin_array.index(key_pin) |
| 85 | + print("Pin #%d is grounded." % i) |
| 86 | + |
| 87 | + led.value = True |
| 88 | + |
| 89 | + while not key_pin.value: |
| 90 | + pass # Wait for release |
| 91 | + |
| 92 | + key = keys_pressed[i] |
| 93 | + if isinstance(key, str): |
| 94 | + keyboard_layout.write(key) |
| 95 | + else: |
| 96 | + keyboard.press(control_key, key) |
| 97 | + keyboard.release_all() |
| 98 | + |
| 99 | + led.value = False |
| 100 | + |
| 101 | + time.sleep(0.01) |
0 commit comments