Skip to content

Commit

Permalink
Merge pull request #12 from asterics/newBLE
Browse files Browse the repository at this point in the history
NewBLE branch merged. Before merging, the master branch was tagged with "PreMergeNewBLE".
  • Loading branch information
ChrisVeigl authored Jul 1, 2018
2 parents 09509cd + 232ce4f commit 625440c
Show file tree
Hide file tree
Showing 96 changed files with 20,220 additions and 2,712 deletions.
58 changes: 27 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
# 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).

A great thank you to Paul Stoffregen for the implementation of the keyboard layouts for his Teensyduino project:
www.pjrc.com
### 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

and to Espressif for providing the HID implementation within the esp-idf.


# Control via stdin (make monitor)

For basic mouse and keyboard testing, this project includes some commands which
can be triggered via the make monitor console.
If there is no command found via this parser, the data is forwarded to the
parser for the second UART (see following chapter).
For basic mouse and keyboard testing, some Bluettooh HID reports can be triggered via the
keyboard when the make monitor console is running (see Espressiv IDF: https://github.com/espressif/esp-idf).

Note: To be sure there is no garbage sent to the second parser, please flush
the buffer via the Enter key. Then type the command and send it via Enter.

|Key|Function |Description|
|---|-----------|-----------|
Expand All @@ -24,34 +23,29 @@ the buffer via the Enter key. Then type the command and send it via Enter.
|w |Mouse up |Move mouse up by 30px |
|l |Click left |Mouse click right |
|r |Click right|Mouse click left |
|Q |Type 'y' |Type the key y with a 1s delay (avoiding endless loops)|
|q |Type 'y' |just for testing keyboard reports|

Any none listed keys are forwarded to the second parser.


# Control via 2nd UART

This interface is primarily used to control this module by an external microcontroller (in our case
either a AVR Mega32U4 in the FABI device or a TeensyLC in the FLipMouse device).
Each command is started with one or two upper letters and a variable number of parameter bytes.
A command must be terminated by a '\n' character!
This interface is primarily used to control mouse / keyboard activities via an external microcontroller.
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)!

TBD: currently the UART is not configured, this parser is just used by the stdin console. After testing all
commands, it will be changed and the configured GPIO pins are stated here.

|Command|Function|Parameters|Description|
|-------|--------|----------|-----------|
|ID|Get ID|--|Prints out the ID of this module, used to determine version or attached module type|
|ID|Get ID|--|Prints out the ID of this module (firmware version number)|
|GP|Get BLE pairings|--|Prints out all paired devices' MAC adress. The order is used for DP as well, starting with 0|
|DP|Delete one pairing|number of pairing, either as ASCII '0'-'9' or 0x00-0x09|Deletes one pairing. The pairing number is determined by the command GP|
|PM|Set pairing mode|'0'/'1' or 0x00/0x01|Enables (1) or disables (0) discovery/advertising and terminates an exisiting connection if enabled|
|ID_FABI|Set BLE device name|--|Set the device name to "FABI" and store permanently. Restarting required.|
|ID_FLIPMOUSE|Set BLE device name|--|Set the device name to "FLipMouse" and store permanently. Restarting required.|
|M|Mouse control|4 Bytes|Issue a mouse HID report, parameter description is below|
|KR|Keyboard, release all|--|Releases all keys & modifiers and sends a HID report|
|KD|Keyboard, key down|1Byte keycode|Adds this keycode to the 6 available key slots and sends a HID report.|
|KU|Keyboard, key up|1Byte keycode|Removes this keycode from the 6 available key slots and sends a HID report.|
|KL|Keyboard, set layout/locale|1Byte|Set the keyboard layout to the given locale number (see below), stored permanently. Restarting required.|
|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.|

Expand All @@ -60,16 +54,18 @@ commands, it will be changed and the configured GPIO pins are stated here.

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

Mouse buttons are assigned as following:
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

Due to the button masks, more than one button might be sent in one command.
Releasing the mouse buttons is done via setting the corresponding mask to zero and
send the mouse command again.
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
Expand Down
69 changes: 69 additions & 0 deletions components/nkolban_BLE/BLE2902.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* BLE2902.cpp
*
* Created on: Jun 25, 2017
* Author: kolban
*/

/*
* See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "BLE2902.h"

BLE2902::BLE2902() : BLEDescriptor(BLEUUID((uint16_t) 0x2902)) {
uint8_t data[2] = {0,0};
setValue(data, 2);
} // BLE2902


/**
* @brief Get the notifications value.
* @return The notifications value. True if notifications are enabled and false if not.
*/
bool BLE2902::getNotifications() {
return (getValue()[0] & (1 << 0)) != 0;
} // getNotifications


/**
* @brief Get the indications value.
* @return The indications value. True if indications are enabled and false if not.
*/
bool BLE2902::getIndications() {
return (getValue()[0] & (1 << 1)) != 0;
} // getIndications


/**
* @brief Set the indications flag.
* @param [in] flag The indications flag.
*/
void BLE2902::setIndications(bool flag) {
uint8_t *pValue = getValue();
if (flag) {
pValue[0] |= 1<<1;
} else {
pValue[0] &= ~(1<<1);
}
} // setIndications


/**
* @brief Set the notifications flag.
* @param [in] flag The notifications flag.
*/
void BLE2902::setNotifications(bool flag) {
uint8_t *pValue = getValue();
if (flag) {
pValue[0] |= 1<<0;
} else {
pValue[0] &= ~(1<<0);
}
} // setNotifications


#endif
34 changes: 34 additions & 0 deletions components/nkolban_BLE/BLE2902.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* BLE2902.h
*
* Created on: Jun 25, 2017
* Author: kolban
*/

#ifndef COMPONENTS_CPP_UTILS_BLE2902_H_
#define COMPONENTS_CPP_UTILS_BLE2902_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "BLEDescriptor.h"

/**
* @brief Descriptor for Client Characteristic Configuration.
*
* This is a convenience descriptor for the Client Characteristic Configuration which has a UUID of 0x2902.
*
* See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml
*/
class BLE2902: public BLEDescriptor {
public:
BLE2902();
bool getNotifications();
bool getIndications();
void setNotifications(bool flag);
void setIndications(bool flag);

}; // BLE2902

#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLE2902_H_ */
74 changes: 74 additions & 0 deletions components/nkolban_BLE/BLE2904.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* BLE2904.cpp
*
* Created on: Dec 23, 2017
* Author: kolban
*/

/*
* See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "BLE2904.h"


BLE2904::BLE2904() : BLEDescriptor(BLEUUID((uint16_t) 0x2904)) {
m_data.m_format = 0;
m_data.m_exponent = 0;
m_data.m_namespace = 1; // 1 = Bluetooth SIG Assigned Numbers
m_data.m_unit = 0;
m_data.m_description = 0;
setValue((uint8_t*)&m_data, sizeof(m_data));
} // BLE2902


/**
* @brief Set the description.
*/
void BLE2904::setDescription(uint16_t description) {
m_data.m_description = description;
setValue((uint8_t*)&m_data, sizeof(m_data));
}


/**
* @brief Set the exponent.
*/
void BLE2904::setExponent(int8_t exponent) {
m_data.m_exponent = exponent;
setValue((uint8_t*)&m_data, sizeof(m_data));
} // setExponent


/**
* @brief Set the format.
*/
void BLE2904::setFormat(uint8_t format) {
m_data.m_format = format;
setValue((uint8_t*)&m_data, sizeof(m_data));
} // setFormat


/**
* @brief Set the namespace.
*/
void BLE2904::setNamespace(uint8_t namespace_value) {
m_data.m_namespace = namespace_value;
setValue((uint8_t*)&m_data, sizeof(m_data));
} // setNamespace


/**
* @brief Set the units for this value. It should be one of the encoded values defined here:
* https://www.bluetooth.com/specifications/assigned-numbers/units
* @param [in] uint The type of units of this characteristic as defined by assigned numbers.
*/
void BLE2904::setUnit(uint16_t unit) {
m_data.m_unit = unit;
setValue((uint8_t*)&m_data, sizeof(m_data));
} // setUnit

#endif
74 changes: 74 additions & 0 deletions components/nkolban_BLE/BLE2904.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* BLE2904.h
*
* Created on: Dec 23, 2017
* Author: kolban
*/

#ifndef COMPONENTS_CPP_UTILS_BLE2904_H_
#define COMPONENTS_CPP_UTILS_BLE2904_H_
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "BLEDescriptor.h"

struct BLE2904_Data {
uint8_t m_format;
int8_t m_exponent;
uint16_t m_unit; // See https://www.bluetooth.com/specifications/assigned-numbers/units
uint8_t m_namespace;
uint16_t m_description;

} __attribute__((packed));

/**
* @brief Descriptor for Characteristic Presentation Format.
*
* This is a convenience descriptor for the Characteristic Presentation Format which has a UUID of 0x2904.
*
* See also:
* https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
*/
class BLE2904: public BLEDescriptor {
public:
BLE2904();
static const uint8_t FORMAT_BOOLEAN = 1;
static const uint8_t FORMAT_UINT2 = 2;
static const uint8_t FORMAT_UINT4 = 3;
static const uint8_t FORMAT_UINT8 = 4;
static const uint8_t FORMAT_UINT12 = 5;
static const uint8_t FORMAT_UINT16 = 6;
static const uint8_t FORMAT_UINT24 = 7;
static const uint8_t FORMAT_UINT32 = 8;
static const uint8_t FORMAT_UINT48 = 9;
static const uint8_t FORMAT_UINT64 = 10;
static const uint8_t FORMAT_UINT128 = 11;
static const uint8_t FORMAT_SINT8 = 12;
static const uint8_t FORMAT_SINT12 = 13;
static const uint8_t FORMAT_SINT16 = 14;
static const uint8_t FORMAT_SINT24 = 15;
static const uint8_t FORMAT_SINT32 = 16;
static const uint8_t FORMAT_SINT48 = 17;
static const uint8_t FORMAT_SINT64 = 18;
static const uint8_t FORMAT_SINT128 = 19;
static const uint8_t FORMAT_FLOAT32 = 20;
static const uint8_t FORMAT_FLOAT64 = 21;
static const uint8_t FORMAT_SFLOAT16 = 22;
static const uint8_t FORMAT_SFLOAT32 = 23;
static const uint8_t FORMAT_IEEE20601 = 24;
static const uint8_t FORMAT_UTF8 = 25;
static const uint8_t FORMAT_UTF16 = 26;
static const uint8_t FORMAT_OPAQUE = 27;

void setDescription(uint16_t);
void setExponent(int8_t exponent);
void setFormat(uint8_t format);
void setNamespace(uint8_t namespace_value);
void setUnit(uint16_t unit);

private:
BLE2904_Data m_data;
}; // BLE2904

#endif /* CONFIG_BT_ENABLED */
#endif /* COMPONENTS_CPP_UTILS_BLE2904_H_ */
Loading

0 comments on commit 625440c

Please sign in to comment.