Skip to content

Commit

Permalink
Add more configurable BLE characteristics
Browse files Browse the repository at this point in the history
  • Loading branch information
lemmingDev authored Sep 26, 2022
1 parent 3f51cc9 commit 884ddba
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 23 deletions.
4 changes: 2 additions & 2 deletions BleConnectionStatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ BleConnectionStatus::BleConnectionStatus(void)
{
}

void BleConnectionStatus::onConnect(NimBLEServer *pServer, ble_gap_conn_desc* desc){
void BleConnectionStatus::onConnect(NimBLEServer *pServer, ble_gap_conn_desc* desc)
{
pServer->updateConnParams(desc->conn_handle, 6, 7, 0, 600);
this->connected = true;

}

void BleConnectionStatus::onDisconnect(NimBLEServer *pServer)
Expand Down
88 changes: 74 additions & 14 deletions BleGamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,30 @@
static const char *LOG_TAG = "BLEGamepad";
#endif

#define SERVICE_UUID_DEVICE_INFORMATION "180A" // Service - Device information

#define CHARACTERISTIC_UUID_MODEL_NUMBER "2A24" // Characteristic - Model Number String - 0x2A24
#define CHARACTERISTIC_UUID_SOFTWARE_REVISION "2A28" // Characteristic - Software Revision String - 0x2A28
#define CHARACTERISTIC_UUID_SERIAL_NUMBER "2A25" // Characteristic - Serial Number String - 0x2A25
#define CHARACTERISTIC_UUID_FIRMWARE_REVISION "2A26" // Characteristic - Firmware Revision String - 0x2A26
#define CHARACTERISTIC_UUID_HARDWARE_REVISION "2A27" // Characteristic - Hardware Revision String - 0x2A27


uint8_t tempHidReportDescriptor[150];
int hidReportDescriptorSize = 0;
uint8_t reportSize = 0;
uint8_t numOfButtonBytes = 0;
uint16_t vid;
uint16_t pid;
uint16_t pid;
uint16_t axesMin;
uint16_t axesMax;
uint16_t simulationMin;
uint16_t simulationMax;

std::string modelNumber;
std::string softwareRevision;
std::string serialNumber;
std::string firmwareRevision;
std::string hardwareRevision;

BleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, uint8_t batteryLevel) : _buttons(),
_specialButtons(0),
Expand Down Expand Up @@ -67,18 +80,24 @@ void BleGamepad::resetButtons()
void BleGamepad::begin(BleGamepadConfiguration *config)
{
configuration = *config; // we make a copy, so the user can't change actual values midway through operation, without calling the begin function again


modelNumber = configuration.getModelNumber();
softwareRevision = configuration.getSoftwareRevision();
serialNumber = configuration.getSerialNumber();
firmwareRevision = configuration.getFirmwareRevision();
hardwareRevision = configuration.getHardwareRevision();

vid = configuration.getVid();
pid = configuration.getPid();

uint8_t high = highByte(vid);
uint8_t low = lowByte(vid);

vid = low << 8 | high;

high = highByte(pid);
low = lowByte(pid);

pid = low << 8 | high;

uint8_t buttonPaddingBits = 8 - (configuration.getButtonCount() % 8);
Expand Down Expand Up @@ -244,15 +263,15 @@ void BleGamepad::begin(BleGamepadConfiguration *config)
// USAGE (Home)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x0A;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x23;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}

if (configuration.getIncludeBack())
{
// USAGE (Back)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x0A;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x24;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}

if (configuration.getIncludeVolumeInc())
Expand Down Expand Up @@ -316,7 +335,7 @@ void BleGamepad::begin(BleGamepadConfiguration *config)
tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getAxesMin());
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00; // Use these two lines for 0 min
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // Use these two lines for -32767 min
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01; // Use these two lines for -32767 min
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x80;

// LOGICAL_MAXIMUM (+32767)
Expand All @@ -325,7 +344,7 @@ void BleGamepad::begin(BleGamepadConfiguration *config)
tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getAxesMax());
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for 255 max
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for +32767 max
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF; // Use these two lines for +32767 max
//tempHidReportDescriptor[hidReportDescriptorSize++] = 0x7F;

// REPORT_SIZE (16)
Expand Down Expand Up @@ -963,6 +982,7 @@ void BleGamepad::setLeftThumb(int16_t x, int16_t y)
sendReport();
}
}

void BleGamepad::setRightThumb(int16_t z, int16_t rZ)
{
if (z == -32768)
Expand Down Expand Up @@ -1325,16 +1345,55 @@ void BleGamepad::setBatteryLevel(uint8_t level)
void BleGamepad::taskServer(void *pvParameter)
{
BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter; // static_cast<BleGamepad *>(pvParameter);

// Use the procedure below to set a custom Bluetooth MAC address
// Compiler adds 0x02 to the last value of board's base MAC address to get the BT MAC address, so take 0x02 away from the value you actually want when setting
//uint8_t newMACAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - 0x02};
//esp_base_mac_addr_set(&newMACAddress[0]); // Set new MAC address

NimBLEDevice::init(BleGamepadInstance->deviceName);
NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(BleGamepadInstance->connectionStatus);

BleGamepadInstance->hid = new NimBLEHIDDevice(pServer);

BleGamepadInstance->inputGamepad = BleGamepadInstance->hid->inputReport(BleGamepadInstance->configuration.getHidReportId()); // <-- input REPORTID from report map
BleGamepadInstance->connectionStatus->inputGamepad = BleGamepadInstance->inputGamepad;

BleGamepadInstance->hid->manufacturer()->setValue(BleGamepadInstance->deviceManufacturer);

NimBLEService *pService = pServer->getServiceByUUID(SERVICE_UUID_DEVICE_INFORMATION);

BLECharacteristic* pCharacteristic_Model_Number = pService->createCharacteristic(
CHARACTERISTIC_UUID_MODEL_NUMBER,
NIMBLE_PROPERTY::READ
);
pCharacteristic_Model_Number->setValue(modelNumber);

BLECharacteristic* pCharacteristic_Software_Revision = pService->createCharacteristic(
CHARACTERISTIC_UUID_SOFTWARE_REVISION,
NIMBLE_PROPERTY::READ
);
pCharacteristic_Software_Revision->setValue(softwareRevision);

BLECharacteristic* pCharacteristic_Serial_Number = pService->createCharacteristic(
CHARACTERISTIC_UUID_SERIAL_NUMBER,
NIMBLE_PROPERTY::READ
);
pCharacteristic_Serial_Number->setValue(serialNumber);

BLECharacteristic* pCharacteristic_Firmware_Revision = pService->createCharacteristic(
CHARACTERISTIC_UUID_FIRMWARE_REVISION,
NIMBLE_PROPERTY::READ
);
pCharacteristic_Firmware_Revision->setValue(firmwareRevision);

BLECharacteristic* pCharacteristic_Hardware_Revision = pService->createCharacteristic(
CHARACTERISTIC_UUID_HARDWARE_REVISION,
NIMBLE_PROPERTY::READ
);
pCharacteristic_Hardware_Revision->setValue(hardwareRevision);

BleGamepadInstance->hid->pnp(0x01, vid, pid, 0x0110);
BleGamepadInstance->hid->hidInfo(0x00, 0x01);

Expand All @@ -1343,8 +1402,9 @@ void BleGamepad::taskServer(void *pvParameter)
uint8_t *customHidReportDescriptor = new uint8_t[hidReportDescriptorSize];
memcpy(customHidReportDescriptor, tempHidReportDescriptor, hidReportDescriptorSize);

for (int i = 0; i < hidReportDescriptorSize; i++)
Serial.printf("%02x", customHidReportDescriptor[i]);
// Testing
//for (int i = 0; i < hidReportDescriptorSize; i++)
// Serial.printf("%02x", customHidReportDescriptor[i]);

BleGamepadInstance->hid->reportMap((uint8_t *)customHidReportDescriptor, hidReportDescriptorSize);
BleGamepadInstance->hid->startServices();
Expand All @@ -1359,4 +1419,4 @@ void BleGamepad::taskServer(void *pvParameter)

ESP_LOGD(LOG_TAG, "Advertising started!");
vTaskDelay(portMAX_DELAY); // delay(portMAX_DELAY);
}
}
17 changes: 16 additions & 1 deletion BleGamepadConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ BleGamepadConfiguration::BleGamepadConfiguration() : _controllerType(CONTROLLER_
_axesMin(0x0000),
_axesMax(0x7FFF),
_simulationMin(0x0000),
_simulationMax(0x7FFF)
_simulationMax(0x7FFF),
_modelNumber("1.0.0"),
_softwareRevision("1.0.0"),
_serialNumber("0123456789"),
_firmwareRevision("0.5.2"),
_hardwareRevision("1.0.0")
{
}

Expand Down Expand Up @@ -107,6 +112,11 @@ bool BleGamepadConfiguration::getIncludeAccelerator() { return _whichSimulationC
bool BleGamepadConfiguration::getIncludeBrake() { return _whichSimulationControls[BRAKE]; }
bool BleGamepadConfiguration::getIncludeSteering() { return _whichSimulationControls[STEERING]; }
const bool *BleGamepadConfiguration::getWhichSimulationControls() const { return _whichSimulationControls; }
char *BleGamepadConfiguration::getModelNumber(){ return _modelNumber; }
char *BleGamepadConfiguration::getSoftwareRevision(){ return _softwareRevision; }
char *BleGamepadConfiguration::getSerialNumber(){ return _serialNumber; }
char *BleGamepadConfiguration::getFirmwareRevision(){ return _firmwareRevision; }
char *BleGamepadConfiguration::getHardwareRevision(){ return _hardwareRevision; }

void BleGamepadConfiguration::setWhichSpecialButtons(bool start, bool select, bool menu, bool home, bool back, bool volumeInc, bool volumeDec, bool volumeMute)
{
Expand Down Expand Up @@ -173,3 +183,8 @@ void BleGamepadConfiguration::setAxesMin(int16_t value) { _axesMin = value; }
void BleGamepadConfiguration::setAxesMax(int16_t value) { _axesMax = value; }
void BleGamepadConfiguration::setSimulationMin(int16_t value) { _simulationMin = value; }
void BleGamepadConfiguration::setSimulationMax(int16_t value) { _simulationMax = value; }
void BleGamepadConfiguration::setModelNumber(char *value) { _modelNumber = value; }
void BleGamepadConfiguration::setSoftwareRevision(char *value) { _softwareRevision = value; }
void BleGamepadConfiguration::setSerialNumber(char *value) { _serialNumber = value; }
void BleGamepadConfiguration::setFirmwareRevision(char *value) { _firmwareRevision = value; }
void BleGamepadConfiguration::setHardwareRevision(char *value) { _hardwareRevision = value; }
16 changes: 15 additions & 1 deletion BleGamepadConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,11 @@ class BleGamepadConfiguration
int16_t _axesMax;
int16_t _simulationMin;
int16_t _simulationMax;

char *_modelNumber;
char *_softwareRevision;
char *_serialNumber;
char *_firmwareRevision;
char *_hardwareRevision;

public:
BleGamepadConfiguration();
Expand Down Expand Up @@ -261,6 +265,11 @@ class BleGamepadConfiguration
int16_t getAxesMax();
int16_t getSimulationMin();
int16_t getSimulationMax();
char *getModelNumber();
char *getSoftwareRevision();
char *getSerialNumber();
char *getFirmwareRevision();
char *getHardwareRevision();

void setControllerType(uint8_t controllerType);
void setAutoReport(bool value);
Expand Down Expand Up @@ -297,6 +306,11 @@ class BleGamepadConfiguration
void setAxesMax(int16_t value);
void setSimulationMin(int16_t value);
void setSimulationMax(int16_t value);
void setModelNumber(char *value);
void setSoftwareRevision(char *value);
void setSerialNumber(char *value);
void setFirmwareRevision(char *value);
void setHardwareRevision(char *value);
};

#endif
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ It would be great however if any improvements are fed back into this version.
- [x] Special buttons (start, select, menu, home, back, volume up, volume down, volume mute) all disabled by default
- [x] Configurable HID descriptor
- [x] Configurable VID and PID values
- [ ] Report optional battery level to host <-- currently disabled
- [x] Customize Bluetooth device name/manufacturer
- [x] Configurable BLE characteristics (name, manufacturer, model number, software revision, serial number, firmware revision, hardware revision)
- [ ] Report optional battery level to host <-- currently disabled <-- awaiting NimBLE support
- [x] Uses efficient NimBLE bluetooth library
- [x] Compatible with Windows
- [x] Compatible with Android (Android OS maps default buttons / axes / hats slightly differently than Windows)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Sets BLE characteristic options
* Also shows how to set a custom MAC address
* Use BLE Scanner etc on Android to see them
*/

#include <Arduino.h>
#include <BleGamepad.h>

BleGamepad bleGamepad("Custom Contoller Name", "lemmingDev", 100); // Set custom device name, manufacturer and initial battery level
BleGamepadConfiguration bleGamepadConfig; // Create a BleGamepadConfiguration object to store all of the options

// Use the procedure below to set a custom Bluetooth MAC address
// Compiler adds 0x02 to the last value of board's base MAC address to get the BT MAC address, so take 0x02 away from the value you actually want when setting
// I've noticed the first number is a little picky and if set incorrectly don't work and will default to the board's embedded address
// 0xAA definately works, so use that, or experiment
uint8_t newMACAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - 0x02};

void setup()
{
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleGamepadConfig.setAutoReport(false);
bleGamepadConfig.setControllerType(CONTROLLER_TYPE_GAMEPAD); // CONTROLLER_TYPE_JOYSTICK, CONTROLLER_TYPE_GAMEPAD (DEFAULT), CONTROLLER_TYPE_MULTI_AXIS
bleGamepadConfig.setVid(0xe502);
bleGamepadConfig.setPid(0xabcd);

bleGamepadConfig.setModelNumber("1.0");
bleGamepadConfig.setSoftwareRevision("Software Rev 1");
bleGamepadConfig.setSerialNumber("9876543210");
bleGamepadConfig.setFirmwareRevision("2.0");
bleGamepadConfig.setHardwareRevision("1.7");

// Some non-Windows operating systems and web based gamepad testers don't like min axis set below 0, so 0 is set by default
//bleGamepadConfig.setAxesMin(0x8001); // -32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepadConfig.setAxesMin(0x0000); // 0 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal
bleGamepadConfig.setAxesMax(0x7FFF); // 32767 --> int16_t - 16 bit signed integer - Can be in decimal or hexadecimal

bleGamepad.begin(&bleGamepadConfig); // Begin gamepad with configuration options
esp_base_mac_addr_set(&newMACAddress[0]); // Set new MAC address
}

void loop()
{
if (bleGamepad.isConnected())
{

}
}
13 changes: 12 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Class
#######################################

BleGamepad KEYWORD1
BleGamepad KEYWORD1
BleGamepadConfiguration KEYWORD1

#######################################
Expand Down Expand Up @@ -134,12 +134,23 @@ getAxesMin KEYWORD2
getAxesMax KEYWORD2
getSimulationMin KEYWORD2
getSimulationMax KEYWORD2
getModelNumber KEYWORD2
getSoftwareRevision KEYWORD2
getSerialNumber KEYWORD2
getFirmwareRevision KEYWORD2
getHardwareRevision KEYWORD2
setVid KEYWORD2
setPid KEYWORD2
setAxesMin KEYWORD2
setAxesMax KEYWORD2
setSimulationMin KEYWORD2
setSimulationMax KEYWORD2
setModelNumber KEYWORD2
setSoftwareRevision KEYWORD2
setSerialNumber KEYWORD2
setFirmwareRevision KEYWORD2
setHardwareRevision KEYWORD2


#######################################
# Constants
Expand Down
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name=ESP32-BLE-Gamepad
version=0.5.1
version=0.5.2
author=lemmingDev
maintainer=lemmingDev
sentence=Bluetooth LE Gamepad library for the ESP32.
paragraph=Bluetooth LE Gamepad library for the ESP32.
category=Communication
url=https://github.com/lemmingDev/ESP32-BLE-Gamepad
architectures=esp32
depends=NimBLE-Arduino
depends=NimBLE-Arduino

0 comments on commit 884ddba

Please sign in to comment.