-
-
Save rmed/0d11b7225b3b772bb0dd89108ee93df0 to your computer and use it in GitHub Desktop.
#!/bin/bash | |
sleep 15 | |
# Create gadget | |
mkdir /sys/kernel/config/usb_gadget/mykeyboard | |
cd /sys/kernel/config/usb_gadget/mykeyboard | |
# Add basic information | |
echo 0x0100 > bcdDevice # Version 1.0.0 | |
echo 0x0200 > bcdUSB # USB 2.0 | |
echo 0x00 > bDeviceClass | |
echo 0x00 > bDeviceProtocol | |
echo 0x00 > bDeviceSubClass | |
echo 0x08 > bMaxPacketSize0 | |
echo 0x0104 > idProduct # Multifunction Composite Gadget | |
echo 0x1d6b > idVendor # Linux Foundation | |
# Create English locale | |
mkdir strings/0x409 | |
echo "My manufacturer" > strings/0x409/manufacturer | |
echo "My virtual keyboard" > strings/0x409/product | |
echo "0123456789" > strings/0x409/serialnumber | |
# Create HID function | |
mkdir functions/hid.usb0 | |
echo 1 > functions/hid.usb0/protocol | |
echo 8 > functions/hid.usb0/report_length # 8-byte reports | |
echo 1 > functions/hid.usb0/subclass | |
# Write report descriptor | |
echo "05010906a101050719e029e71500250175019508810275089501810175019503050819012903910275019505910175089506150026ff00050719002aff008100c0" | xxd -r -ps > functions/hid.usb0/report_desc | |
# Create configuration | |
mkdir configs/c.1 | |
mkdir configs/c.1/strings/0x409 | |
echo 0x80 > configs/c.1/bmAttributes | |
echo 200 > configs/c.1/MaxPower # 200 mA | |
echo "Example configuration" > configs/c.1/strings/0x409/configuration | |
# Link HID function to configuration | |
ln -s functions/hid.usb0 configs/c.1 | |
# Enable gadget | |
ls /sys/class/udc > UDC | |
sleep 15 | |
/usr/local/bin/tester.sh & | |
# /usr/local/bin/tester.py & |
#!/usr/bin/env python3 | |
# | |
# Python file to test the gadget by writing "Hello World!" | |
# If used with the configfs_test.sh, place this file under /usr/local/bin/tester.py | |
# and uncomment the appropriate line | |
NULL_CHAR = chr(0) | |
def write_report(report): | |
with open('/dev/hidg0', 'rb+') as fd: | |
fd.write(report.encode()) | |
# H (press shift and H) | |
write_report(chr(32)+NULL_CHAR+chr(11)+NULL_CHAR*5) | |
# e | |
write_report(NULL_CHAR*2+chr(8)+NULL_CHAR*5) | |
# ll | |
write_report(NULL_CHAR*2+chr(15)+NULL_CHAR*5) | |
write_report(NULL_CHAR*8) | |
write_report(NULL_CHAR*2+chr(15)+NULL_CHAR*5) | |
# o | |
write_report(NULL_CHAR*2+chr(18)+NULL_CHAR*5) | |
# SPACE | |
write_report(NULL_CHAR*2+chr(44)+NULL_CHAR*5) | |
# W (press shift and W) | |
write_report(chr(32)+NULL_CHAR+chr(26)+NULL_CHAR*5) | |
# o | |
write_report(NULL_CHAR*2+chr(18)+NULL_CHAR*5) | |
# r | |
write_report(NULL_CHAR*2+chr(21)+NULL_CHAR*5) | |
# l | |
write_report(NULL_CHAR*2+chr(15)+NULL_CHAR*5) | |
# d | |
write_report(NULL_CHAR*2+chr(7)+NULL_CHAR*5) | |
# ! (press shift and 1) | |
write_report(chr(32)+NULL_CHAR+chr(30)+NULL_CHAR*5) | |
# Release all keys | |
write_report(NULL_CHAR*8) |
#!/bin/bash | |
# | |
# Bash file to test the gadget by writing "Hello World!" | |
# If used with the configfs_test.sh, place this file under /usr/local/bin/tester.sh | |
# and uncomment the appropriate line | |
function write_report { | |
echo -ne $1 > /dev/hidg0 | |
} | |
# H (press shift and H) | |
write_report "\x20\0\xb\0\0\0\0\0" | |
# e | |
write_report "\0\0\x8\0\0\0\0\0" | |
# ll | |
write_report "\0\0\xf\0\0\0\0\0" | |
write_report "\0\0\0\0\0\0\0\0" | |
write_report "\0\0\xf\0\0\0\0\0" | |
# o | |
write_report "\0\0\x12\0\0\0\0\0" | |
# SPACE | |
write_report "\0\0\x2c\0\0\0\0\0" | |
# W (press shift and W) | |
write_report "\x20\0\x1a\0\0\0\0\0" | |
# o | |
write_report "\0\0\x12\0\0\0\0\0" | |
# r | |
write_report "\0\0\x21\0\0\0\0\0" | |
# l | |
write_report "\0\0\xf\0\0\0\0\0" | |
# d | |
write_report "\0\0\x7\0\0\0\0\0" | |
# ! (press shift and 1) | |
write_report "\x20\0\x1e\0\0\0\0\0" | |
# Release al keys | |
write_report "\0\0\0\0\0\0\0\0" |
@rmed: Great blog post! (https://www.rmedgar.com/blog/using-rpi-zero-as-keyboard-setup-and-device-definition) Where is tester.sh or tester.py? I would like to get more information on setting up sending keystrokes via USB. I'm making a little password vault/manager gadget and it would be great to be able to send the password input over USB.
@zbeekman: I updated the gist with the Python and Bash scripts I used to test the gadget config, they simply write Hello World!
by emulating each keystroke. Hope this helps!
@rmed: Thanks for the tutorial, but I am having some problems. When I run configfs.sh
. I get this:
./tempinstall.sh: line 29: echo: write error: Device or resource busy ./tempinstall.sh: line 30: echo: write error: Device or resource busy ./tempinstall.sh: line 31: echo: write error: Device or resource busy xxd: Device or resource busy ln: failed to create symbolic link 'configs/c.1/hid.usb0': File exists ls: write error: Device or resource busy
@flash76 Seems like the device already exists when you try to execute the script. Is there any gadget preconfigured in the RPi (e.g. ethernet over USB)?
Hi.
I have orange pi device and i want use keyboard gadget.
I setup it with this script and it work in gedit terminal and so on on my local machine/
But when i try it to connect to my macbook it doesn't work.
At first i think usb on my book doesn't work. But if i connect usb keyboard it perfectly work.
So how i can "clone" my existing keyboard with libcompose?
I'm not having any luck getting this going. I have Stretch Lite 2018-06-27 flashed on my Pi0W. The configfs_test.sh and tester.sh scripts in the right place, and it seems like the initialization works, looking at dmesg. tester.sh hangs forever however :/
tested and working on pi0w
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
NAME="Raspbian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)
@rmed, in https://gist.github.com/rmed/0d11b7225b3b772bb0dd89108ee93df0#file-configfs_test-sh-L45 you seem to want to create a symbolic link [something] to configs/c.1
but just before you have created a directory named configs/c.1
Isn't that an error ?
Nevermind I got it : it's like a copy, the actual symlink will be created into configs/c.1/
🤕
Anyone have an idea of how to send the combination of "CTRL"+"SHIFT"+"1" keys?
Anyone have an idea of how to send the combination of "CTRL"+"SHIFT"+"1" keys?
Try the following (using the Python example):
write_report(chr(48)+NULL_CHAR+chr(30)+NULL_CHAR*5)
Hi, I wrote it according to the script of configfs_test.sh , but when I plugged in the device, no hidg0 driver was found in the /dev directory.
I was having problems with this, but I have a otg hub with a turn around on one of the of the USB ports. has anyone tried this before? i have build an arcade stick using RPi gpio pins for inputs. I might need to disconnect the hub and use a different cable. kinda annoying.
RetroPie, Linux 5.10.0 Raspberry Pi Zero W
my goal is to send keystrokes via the gpio to a windows pc when plugged in, otherwise it uses retrogame to to map gpio to keys for my attractmode setup. I have 25 inputs configured
just so you have an idea of what I'm talking about, the photos are above.
I was having problems with this, but I have a otg hub with a turn around on one of the of the USB ports. has anyone tried this before? i have build an arcade stick using RPi gpio pins for inputs. I might need to disconnect the hub and use a different cable. kinda annoying.
RetroPie, Linux 5.10.0 Raspberry Pi Zero W
my goal is to send keystrokes via the gpio to a windows pc when plugged in, otherwise it uses retrogame to to map gpio to keys for my attractmode setup. I have 25 inputs configured
just so you have an idea of what I'm talking about, the photos are above.
Last time I tried using a hub the Pi Zero was not able to configure the data port to act as a device rather than a host. Not sure it is possible to make use of a hub and send keystrokes at the same time.
Hello @rmed, thanks for the blog post, it's the most clearer about HID with RPi Zero that I ever saw.
@flash76 Seems like the device already exists when you try to execute the script. Is there any gadget preconfigured in the RPi (e.g. ethernet over USB)?
Related to this, I'm trying to use a RPi Zero (not the W), but to have access to the terminal, I need to use the data micro USB, and I'm having the same problem that @flash76 had about the resource being busy, do you have any way that I could make it happen?
not sure if this is my case only
tester.sh - line 34 ~ 35
# r
write_report "\0\0\x21\0\0\0\0\0"
this report typed "4" instead of "r"
so I changed that 21 to 15 and works fine for me
(Reference: https://usb.org/sites/default/files/hut1_21.pdf Chaprter 10)
Hello @rmed, thanks for the blog post, it's the most clearer about HID with RPi Zero that I ever saw.
@flash76 Seems like the device already exists when you try to execute the script. Is there any gadget preconfigured in the RPi (e.g. ethernet over USB)?
Related to this, I'm trying to use a RPi Zero (not the W), but to have access to the terminal, I need to use the data micro USB, and I'm having the same problem that @flash76 had about the resource being busy, do you have any way that I could make it happen?
I don't know if this is related. I added "chown pi /dev/hidg0" at the end of the startup script so that the device is available to the regular user "pi".
any idea how to write code to move the mouse? I have this but I can only move the mouse to the right and down as it's a syntax error to use negative values for the chr?
#!/usr/bin/env python3
NULL_CHAR = chr(0)
import time
def ms_write(report):
with open("/dev/hidg1", "wb+") as fd:
fd.write(report.encode())
ms_write(chr(1)+chr(0)+chr(0))
ms_write(NULL_CHAR*3)
any idea how to write code to move the mouse? I have this but I can only move the mouse to the right and down as it's a syntax error to use negative values for the chr?
#!/usr/bin/env python3 NULL_CHAR = chr(0) import time
def ms_write(report): with open("/dev/hidg1", "wb+") as fd: fd.write(report.encode())
ms_write(chr(1)+chr(0)+chr(0)) ms_write(NULL_CHAR*3)
While chr()
is good for simple cases (or those that don't need negative values), I'd say you need to use the int.to_bytes()
method (https://docs.python.org/3/library/stdtypes.html#int.to_bytes), which will allow you to specify that the value to convert is signed and needs to be stored in a single byte.
Tested on Raspbian Stretch (lite) 2018-06-27.