Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions BleFeatureReport.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "BleFeatureReport.h"

BleFeatureReceiver::BleFeatureReceiver(uint16_t featureReportLength)
{
this->featureReportLength = featureReportLength;
featureBuffer = new uint8_t[featureReportLength];
}

BleFeatureReceiver::~BleFeatureReceiver()
{
// Release memory
if (featureBuffer)
{
delete[] featureBuffer;
}
}

void BleFeatureReceiver::onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo& connInfo)
{
// Set data for the host
pCharacteristic->setValue(featureBuffer, featureReportLength);

featureFlag = true;
}

void BleFeatureReceiver::onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo& connInfo)
{
// Retrieve data sent from the host
std::string value = pCharacteristic->getValue();

if (value.length() <= featureReportLength) {
// Check if data has changed
if (memcmp(value.c_str(), featureBuffer, value.length()) != 0) {
memcpy(featureBuffer, value.c_str(), value.length());
// If there's a callback defined, call it
//if (_onFeatureReportReceived) {
// _onFeatureReportReceived((const uint8_t*)value.c_str(), value.length());
//}
}
}

/*

// Store the received data in the buffer
for (int i = 0; i < std::min(value.length(), (size_t)featureReportLength); i++)
{
featureBuffer[i] = (uint8_t)value[i];
}

*/

// Testing
// Serial.println("Received data from host:");
// for (size_t i = 0; i < value.length(); i++) {
// Serial.print((uint8_t)value[i], HEX);
// Serial.print(" ");
// }
// Serial.println();

featureFlag = true;
}
27 changes: 27 additions & 0 deletions BleFeatureReport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef BLE_FEATURE_REPORT_H
#define BLE_FEATURE_REPORT_H
#include "sdkconfig.h"
#if defined(CONFIG_BT_ENABLED)

#include "nimconfig.h"
#if defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)

#include <NimBLEServer.h>
#include "NimBLECharacteristic.h"
#include "NimBLEConnInfo.h"

class BleFeatureReceiver : public NimBLECharacteristicCallbacks
{
public:
BleFeatureReceiver(uint16_t featureReportLength);
~BleFeatureReceiver();
void onRead(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo& connInfo) override;
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo& connInfo) override;
bool featureFlag = false;
uint16_t featureReportLength;
uint8_t *featureBuffer;
};

#endif // CONFIG_BT_NIMBLE_ROLE_PERIPHERAL
#endif // CONFIG_BT_ENABLED
#endif // BLE_FEATURE_REPORT_H
84 changes: 84 additions & 0 deletions BleGamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,12 @@ BleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, u
hidReportDescriptorSize = 0;
hidReportSize = 0;
numOfButtonBytes = 0;

enableOutputReport = false;
outputReportLength = 64;
enableFeatureReport = false;
featureReportLength = 64;

nusInitialized = false;
}

Expand All @@ -101,6 +105,8 @@ void BleGamepad::begin(BleGamepadConfiguration *config)

enableOutputReport = configuration.getEnableOutputReport();
outputReportLength = configuration.getOutputReportLength();
enableFeatureReport = configuration.getEnableFeatureReport();
featureReportLength = configuration.getFeatureReportLength();

uint8_t buttonPaddingBits = 8 - (configuration.getButtonCount() % 8);
if (buttonPaddingBits == 8)
Expand Down Expand Up @@ -738,6 +744,53 @@ void BleGamepad::begin(BleGamepadConfiguration *config)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}

if (configuration.getEnableFeatureReport())
{
// Usage Page (Vendor Defined 0xFF00)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x06;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF;

// Usage (Vendor Usage 0x01)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;

// Usage (0x01)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;

// Logical Minimum (0)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;

// Logical Maximum (255)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x26;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;

// Report Size (8 bits)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x08;

if (configuration.getFeatureReportLength() <= 0xFF)
{
// Report Count (0~255 bytes)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = configuration.getFeatureReportLength();
}
else
{
// Report Count (0~65535 bytes)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x96;
tempHidReportDescriptor[hidReportDescriptorSize++] = lowByte(configuration.getFeatureReportLength());
tempHidReportDescriptor[hidReportDescriptorSize++] = highByte(configuration.getFeatureReportLength());
}

// Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xB1;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}

// END_COLLECTION (Application)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;

Expand Down Expand Up @@ -1645,6 +1698,29 @@ uint8_t* BleGamepad::getOutputBuffer()
return nullptr;
}

bool BleGamepad::isFeatureReceived()
{
if (enableFeatureReport && featureReceiver)
{
if (this->featureReceiver->featureFlag)
{
this->featureReceiver->featureFlag = false; // Clear Flag
return true;
}
}
return false;
}

uint8_t* BleGamepad::getFeatureBuffer()
{
if (enableFeatureReport && featureReceiver)
{
memcpy(featureBackupBuffer, featureReceiver->featureBuffer, featureReportLength); // Creating a backup to avoid buffer being overwritten while processing data
return featureBackupBuffer;
}
return nullptr;
}

bool BleGamepad::deleteAllBonds(bool resetBoard)
{
bool success = false;
Expand Down Expand Up @@ -1996,6 +2072,14 @@ void BleGamepad::taskServer(void *pvParameter)
BleGamepadInstance->outputGamepad->setCallbacks(BleGamepadInstance->outputReceiver);
}

if (BleGamepadInstance->enableFeatureReport)
{
BleGamepadInstance->featureGamepad = BleGamepadInstance->hid->getFeatureReport(BleGamepadInstance->configuration.getHidReportId());
BleGamepadInstance->featureReceiver = new BleFeatureReceiver(BleGamepadInstance->featureReportLength);
BleGamepadInstance->featureBackupBuffer = new uint8_t[BleGamepadInstance->featureReportLength];
BleGamepadInstance->featureGamepad->setCallbacks(BleGamepadInstance->featureReceiver);
}

BleGamepadInstance->hid->setManufacturer(BleGamepadInstance->deviceManufacturer);

NimBLEService *pService = pServer->getServiceByUUID(SERVICE_UUID_DEVICE_INFORMATION);
Expand Down
8 changes: 8 additions & 0 deletions BleGamepad.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "NimBLECharacteristic.h"
#include "BleGamepadConfiguration.h"
#include "BleOutputReceiver.h"
#include "BleFeatureReport.h"
#include "BleNUS.h"

class BleGamepad
Expand All @@ -24,6 +25,8 @@ class BleGamepad
uint8_t numOfButtonBytes;
bool enableOutputReport;
uint16_t outputReportLength;
bool enableFeatureReport;
uint16_t featureReportLength;
uint8_t _buttons[16]; // 8 bits x 16 bytes = 128 bits --> 128 button max
uint8_t _specialButtons;
int16_t _x;
Expand Down Expand Up @@ -57,15 +60,18 @@ class BleGamepad

BleConnectionStatus *connectionStatus;
BleOutputReceiver *outputReceiver;
BleFeatureReceiver *featureReceiver;
NimBLEServer *pServer;
BleNUS* nus;

NimBLEHIDDevice *hid;
NimBLECharacteristic *inputGamepad;
NimBLECharacteristic *outputGamepad;
NimBLECharacteristic *featureGamepad;
NimBLECharacteristic *pCharacteristic_Power_State;

uint8_t *outputBackupBuffer;
uint8_t *featureBackupBuffer;

void rawAction(uint8_t msg[], char msgSize);
static void taskServer(void *pvParameter);
Expand Down Expand Up @@ -143,6 +149,8 @@ class BleGamepad
bool delayAdvertising;
bool isOutputReceived();
uint8_t* getOutputBuffer();
bool isFeatureReceived();
uint8_t* getFeatureBuffer();
bool deleteBond(bool resetBoard = false);
bool deleteAllBonds(bool resetBoard = false);
bool enterPairingMode();
Expand Down
18 changes: 12 additions & 6 deletions BleGamepadConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ BleGamepadConfiguration::BleGamepadConfiguration() : _controllerType(CONTROLLER_
_firmwareRevision("0.7.4"),
_hardwareRevision("1.0.0"),
_enableOutputReport(false),
_enableFeatureReport(false),
_enableNordicUARTService(false),
_outputReportLength(64),
_transmitPowerLevel(9)
_featureReportLength(64),
_transmitPowerLevel(9)
{
}

Expand Down Expand Up @@ -126,14 +128,16 @@ bool BleGamepadConfiguration::getIncludeSteering() { return _whichSimulationCont
const bool *BleGamepadConfiguration::getWhichSimulationControls() const { return _whichSimulationControls; }
bool BleGamepadConfiguration::getIncludeGyroscope() { return _includeGyroscope; }
bool BleGamepadConfiguration::getIncludeAccelerometer() { return _includeAccelerometer; }
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; }
const char *BleGamepadConfiguration::getModelNumber(){ return _modelNumber; }
const char *BleGamepadConfiguration::getSoftwareRevision(){ return _softwareRevision; }
const char *BleGamepadConfiguration::getSerialNumber(){ return _serialNumber; }
const char *BleGamepadConfiguration::getFirmwareRevision(){ return _firmwareRevision; }
const char *BleGamepadConfiguration::getHardwareRevision(){ return _hardwareRevision; }
bool BleGamepadConfiguration::getEnableOutputReport(){ return _enableOutputReport; }
bool BleGamepadConfiguration::getEnableFeatureReport(){ return _enableFeatureReport; }
bool BleGamepadConfiguration::getEnableNordicUARTService(){ return _enableNordicUARTService; }
uint16_t BleGamepadConfiguration::getOutputReportLength(){ return _outputReportLength; }
uint16_t BleGamepadConfiguration::getFeatureReportLength(){ return _featureReportLength; }
int8_t BleGamepadConfiguration::getTXPowerLevel(){ return _transmitPowerLevel; } // Returns the power level that was set as the server started

void BleGamepadConfiguration::setWhichSpecialButtons(bool start, bool select, bool menu, bool home, bool back, bool volumeInc, bool volumeDec, bool volumeMute)
Expand Down Expand Up @@ -212,6 +216,8 @@ void BleGamepadConfiguration::setSerialNumber(char *value) { _serialNumber = val
void BleGamepadConfiguration::setFirmwareRevision(char *value) { _firmwareRevision = value; }
void BleGamepadConfiguration::setHardwareRevision(char *value) { _hardwareRevision = value; }
void BleGamepadConfiguration::setEnableOutputReport(bool value) { _enableOutputReport = value; }
void BleGamepadConfiguration::setEnableFeatureReport(bool value) { _enableFeatureReport = value; }
void BleGamepadConfiguration::setEnableNordicUARTService(bool value) { _enableNordicUARTService = value; }
void BleGamepadConfiguration::setOutputReportLength(uint16_t value) { _outputReportLength = value; }
void BleGamepadConfiguration::setFeatureReportLength(uint16_t value) { _featureReportLength = value; }
void BleGamepadConfiguration::setTXPowerLevel(int8_t value) { _transmitPowerLevel = value; }
32 changes: 19 additions & 13 deletions BleGamepadConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,17 @@ class BleGamepadConfiguration
int16_t _simulationMax;
int16_t _motionMin;
int16_t _motionMax;
char *_modelNumber;
char *_softwareRevision;
char *_serialNumber;
char *_firmwareRevision;
char *_hardwareRevision;
const char *_modelNumber;
const char *_softwareRevision;
const char *_serialNumber;
const char *_firmwareRevision;
const char *_hardwareRevision;
bool _enableOutputReport;
bool _enableFeatureReport;
bool _enableNordicUARTService;
uint16_t _outputReportLength;
int8_t _transmitPowerLevel;
uint16_t _featureReportLength;
int8_t _transmitPowerLevel;


public:
Expand Down Expand Up @@ -291,15 +293,17 @@ class BleGamepadConfiguration
int16_t getSimulationMax();
int16_t getMotionMin();
int16_t getMotionMax();
char *getModelNumber();
char *getSoftwareRevision();
char *getSerialNumber();
char *getFirmwareRevision();
char *getHardwareRevision();
const char *getModelNumber();
const char *getSoftwareRevision();
const char *getSerialNumber();
const char *getFirmwareRevision();
const char *getHardwareRevision();
bool getEnableOutputReport();
bool getEnableFeatureReport();
bool getEnableNordicUARTService();
uint16_t getOutputReportLength();
int8_t getTXPowerLevel();
uint16_t getFeatureReportLength();
int8_t getTXPowerLevel();

void setControllerType(uint8_t controllerType);
void setAutoReport(bool value);
Expand Down Expand Up @@ -347,9 +351,11 @@ class BleGamepadConfiguration
void setFirmwareRevision(char *value);
void setHardwareRevision(char *value);
void setEnableOutputReport(bool value);
void setEnableFeatureReport(bool value);
void setEnableNordicUARTService(bool value);
void setOutputReportLength(uint16_t value);
void setTXPowerLevel(int8_t value);
void setFeatureReportLength(uint16_t value);
void setTXPowerLevel(int8_t value);
};

#endif