Skip to content

Commit

Permalink
Merge pull request #35 from asterics/bumpEspressifExample
Browse files Browse the repository at this point in the history
Updated Espressif example, fixing many compatibility issues with Win10/iOS (especially accessible switch control & assistive touch bugs)
  • Loading branch information
Benjamin Aigner authored Jun 29, 2020
2 parents bb5132e + b6c73ed commit f27a45a
Show file tree
Hide file tree
Showing 22 changed files with 1,240 additions and 10,757 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

set(SUPPORTED_TARGETS esp32)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32_mouse_keyboard)
157 changes: 72 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,76 @@
# ESP32 Mouse/Keyboard for BLE HID
ESP32 implementation for HID over GATT Keyboard and Mouse (Bluetooth Low Energy). Including serial API for external modules (similar to Adafruit EZKey HID).
ESP32 implementation for HID over GATT Keyboard and Mouse (Bluetooth Low Energy). Including serial API for external modules (compatible to Adafruit EZKey HID).

## Building the ESP32 firmware
## Compatibility

Please follow the step-by-step instructions of Espressif's ESP-IDF manual to setup the build infrastructure:
[Setup Toolchain](https://esp-idf.readthedocs.io/en/latest/get-started/index.html#setup-toolchain)
Due to the wide variety of hardware & software combinations, it is hard to guarantee compatibility.
Nevertheless, we try to test this project with as much devices as possible.

Tested devices by the AsTeRICS team:

__Note:__ Due to frequent breaking changes within the esp-idf and all build tools, we recommend to use a specific version of the tools:
* release v4.1 (on 04.02.2020)
* master branch (on 04.02.2020)
| Device | Mouse | Keyboard |
|--------------|-------|----------|
|PC with CSR 4.0 BT dongle, Debian Bullseye | yes | yes |
|Lenovo T440s, Debian Buster | yes | yes |
|PC with CSR 4.0 BT dongle, Win10 Build 2004 | yes | yes |
|Lenovo T440s, Win10 Build 2004 in VirtualBox | no | no |
|Xiaomi Mi A1 - LineageOS 16.0 (Android 9) | yes | yes |
|Asus Nexus 7 (2013) - Android 6.0.1 | yes | yes |
|iPad Air 2 (MGL12FD/A9 - iOS 13.3.1 | yes (Assistive Touch) | yes (Text input & accessible switch interface) |
|iPad Air 2 (MGL12FD/A9 - iOS 13.5.1 | yes (Assistive Touch) | yes (Text input & accessible switch interface) |
|iPad Pro 10.5" (MPHG2TY/A) - iOS 13.5.1 | yes (Assistive Touch) | yes (Text input & accessible switch interface) |
|iPad 6th Gen (MR7J2FD/A) - iOS 13.5.1 | yes (Assistive Touch) | yes (Text input & accessible switch interface) |

To get this version, use the following commands:

`git clone -b release/v4.1 --recursive https://github.com/espressif/esp-idf.git`
`cd esp-idf`
`./install.sh`
`. ./export.sh`
_Note:_ On some iPad devices, there might show up a notification in the Bluetooth menu, that this device may affect WiFi or Bluetooth performance.
You could ignore this error, according to [StackOverflow](https://apple.stackexchange.com/questions/386589/what-does-using-mx-anywhere-2s-may-affect-wi-fi-and-bluetooth-connectivity-mea) there is no clear
reason for this message, maybe it is related to the additional WiFi interface of the ESP32 (other user report this error if a normal mouse has an additional USB-dongle).


__Now change your directory into the root directory of this repository.__
_Note:_ If you can report the compatibility status for a device, we would be happy to add a list of community tested devices, just open an issue with the label __device-testreport__.

After a successful setup, you should be able to build the firmware by executing 'make flash monitor'.
## Building the ESP32 firmware

Please follow the step-by-step instructions of Espressif's ESP-IDF manual to setup the build infrastructure:
[Setup Toolchain](https://esp-idf.readthedocs.io/en/latest/get-started/index.html#setup-toolchain)

With `idf.py build` or `make` you can build this project.

With `idf.py -p (PORT) flash` or `make flash` you can upload this build to an ESP32

With `idf.py -p (PORT) monitor` or `make monitor` you can see the debug output (please use this output if you open an issue) or trigger basic test commands (mouse movement or a keyboard key press) on
a connected target.

# Usage via Console or second UART

## Control via stdin (make monitor)

For basic mouse and keyboard testing, some Bluettooh HID reports can be triggered via the
For basic mouse and keyboard testing, some Bluetooth HID reports can be triggered via the
keyboard when the make monitor console is running (see Espressif IDF docs: https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/tools/idf-monitor.html ).


|Key|Function |Description|
|---|-----------|-----------|
|a |Mouse left |Move mouse left by 30px |
|s |Mouse down |Move mouse down by 30px |
|d |Mouse right|Move mouse right by 30px |
|w |Mouse up |Move mouse up by 30px |
|a |Mouse left |Move mouse left by 30px (`MOUSE_SPEED` define) |
|s |Mouse down |Move mouse down by 30px (`MOUSE_SPEED` define) |
|d |Mouse right|Move mouse right by 30px (`MOUSE_SPEED` define) |
|w |Mouse up |Move mouse up by 30px (`MOUSE_SPEED` define) |
|l |Click left |Mouse click right |
|r |Click right|Mouse click left |
|q |Type 'y' |just for testing keyboard reports|
|q |Type 'y' (US layout) |just for testing keyboard reports|



## Control via 2nd UART

This interface is primarily used to control mouse / keyboard activities via an external microcontroller.


### Commands

Each command is started with a '$' character, followed by a command name (uppercase letters) and a variable number of parameters.
A command must be terminated by a '\n' character (LF, ASCII value 10)!

_Note:_ We do not test these on a regular basis!

|Command|Function|Parameters|Description|
|-------|--------|----------|-----------|
Expand All @@ -58,79 +79,45 @@ A command must be terminated by a '\n' character (LF, ASCII value 10)!
|$DP|Delete one pairing|number of pairing, given as ASCII-characer '0'-'9'|Deletes one pairing. The pairing number is determined by the command GP|
|$PM|Set pairing mode|'0' / '1'|Enables (1) or disables (0) discovery/advertising and terminates an exisiting connection if enabled|
|$NAME|Set BLE device name|name as ASCII string|Set the device name to the given name. Restart required.|
|$M|Mouse control|4 ASCII-integer values (seperated by space or comma)|Issue a mouse HID report, parameter description is below|
|$KA|Keyboard, release all|--|Releases all keys & modifiers and sends a HID report|
|$KH|Keyboard, key hold|keycode as ASCII integer value|Adds this keycode to the 6 available key slots and sends a HID report.|
|$KR|Keyboard, key release|keycode as ASCII integer value|Removes this keycode from the 6 available key slots and sends a HID report.|
|$KL|Keyboard, set layout/locale|locale code as ASCII integer value|Set the keyboard layout to the given locale number (see below), stored permanently. Restarting required.|
|$KW|Keyboard write text|n Bytes|Write a text via the keyboard. Supported are ASCII as well as UTF8 character streams.|
|$KC|Keyboard get keycode for character|2 Bytes|Get a corresponding keycode for the given character. 2 Bytes are parsed for UTF8, if there is only a ASCII character, use the first sent byte only.|


## Mouse command

|Command byte|Param1|Param2|Param3|Param4|
|------------|------|------|------|------|
|'M' |uint8 buttons|int8 X|int8 Y|int8 scroll wheel|

Mouse buttons are encoded as bit values in the parameter 'buttons' as follows:
(1<<0): Left mouse button
(1<<1): Right mouse button
(1<<2): Middle mouse button

Example: "M 3 10 -10 0"

Due to this encoding in a bitmask, more than one button might be sent in one command.
Releasing the mouse buttons is done via setting the corresponding bit postition to zero and
sending the mouse command again.


## Keyboard layouts/locales

|Number|Layout|
|------|------|
|0x00/0| US English (no Unicode)|
|0x01/1| US International|
|0x02/2| German|
|0x03/3| German Mac|
|0x04/4| Canadian (French)|
|0x05/5| Canadian (Multilingual)|
|0x06/6| United Kingdom|
|0x07/7| Finnish|
|0x08/8| French|
|0x09/9| Danish|
|0x0A/10| Norwegian|
|0x0B/11| Swedish|
|0x0C/12| Spanish|
|0x0D/13| Portuguese|
|0x0E/14| Italian|
|0x0F/15| Portuguese (Brazilian)|
|0x10/16| Belgian (French)|
|0x11/17| German (Switzerland)|
|0x12/18| French (Switzerland)|
|0x13/19| Spanish (Latin America)|
|0x14/20| Irish|
|0x15/21| Icelandic|
|0x16/22| Turkish|
|0x17/23| Czech|
|0x18/24| Serbian (Latin only)|

Setting a keyboard locale is done with the "KL" command. Changes taking effect after a restart of the ESP32. This is necessary for initializing the HID country code accordingly.

## RAW HID input

If you want to send HID inputs directly, it is possible to send an HID report directly via:

### HID input

We use a format which is compatible to the Adafruit EZKey module, and added a few backwards compatible features.

__Mouse:__

|Byte 0|Byte 1|Byte 2|Byte 3|Byte 4|Byte 5|Byte 6|Byte 7|Byte 8|
|------|------|------|------|------|------|------|------|------|
| 0xFD | don't care | 0x03 | button mask | X-axis | Y-axis | wheel | don't care | don't care |


__Keyboard:__

_Note:_ currently we only support the US keyboard layout.

|Byte 0|Byte 1|Byte 2|Byte 3|Byte 4|Byte 5|Byte 6|Byte 7|Byte 8|
|------|------|------|------|------|------|------|------|------|
| 0xFD | modifier mask | don't care | keycode 1 | keycode 2 | keycode 3 | keycode 4 | keycode 5 | keycode 6 |


## RAW HID input from sourcecode

If you want to change anything within the sourcecode, it is possible to send an HID report directly via:

```
hid_dev_send_report(hidd_le_env.gatt_if, hid_conn_id,
HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT, HID_MOUSE_IN_RPT_LEN, mouse_report);
```

Use according `HID_RPT_ID_*`/`HID_*_IN_RPT_LEN`, depending on input type (mouse, keyboard, absolute mouse, joystick).
Use according `HID_RPT_ID_*`/`HID_*_IN_RPT_LEN`, depending on input type (mouse, keyboard).
The HID report data is located in array, passed as last parameter of `hid_dev_send_report`.

## Mouse & Keyboard input from sourcecode

Please use the functions provided by `esp_hidd_prf_api.c`.


### Credits and many thanks to:
## Credits and many thanks to:
- Paul Stoffregen for the implementation of the keyboard layouts for his Teensyduino project: www.pjrc.com
- Neil Kolban for his great contributions to the ESP32 SW (in particular the Bluetooth support): https://github.com/nkolban
- Chegewara for help and support
Expand Down
7 changes: 7 additions & 0 deletions main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
idf_component_register(SRCS "ble_hidd_demo_main.c"
"esp_hidd_prf_api.c"
"hid_dev.c"
"hid_device_le_prf.c"
INCLUDE_DIRS ".")

target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable)
8 changes: 0 additions & 8 deletions main/ble_hid/CMakeLists.txt

This file was deleted.

4 changes: 0 additions & 4 deletions main/ble_hid/component.mk

This file was deleted.

Loading

0 comments on commit f27a45a

Please sign in to comment.