Files
ESP32-BLE-Gamepad/BleGamepad.cpp
Hagedoorn, J.P. (pieter) a7f4116eb1 added back button
2022-04-25 16:38:04 +02:00

1028 lines
28 KiB
C++

#include <NimBLEDevice.h>
#include <NimBLEUtils.h>
#include <NimBLEServer.h>
#include "NimBLEHIDDevice.h"
#include "HIDTypes.h"
#include "HIDKeyboardTypes.h"
#include <driver/adc.h>
#include "sdkconfig.h"
#include "BleConnectionStatus.h"
#include "BleGamepad.h"
#if defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
#define LOG_TAG "BLEGamepad"
#else
#include "esp_log.h"
static const char* LOG_TAG = "BLEGamepad";
#endif
uint8_t tempHidReportDescriptor[150];
int hidReportDescriptorSize = 0;
uint8_t _hidReportId = 3;
uint8_t reportSize = 0;
uint8_t numOfButtonBytes = 0;
BleGamepad::BleGamepad(std::string deviceName, std::string deviceManufacturer, uint8_t batteryLevel) :
_controllerType(CONTROLLER_TYPE_GAMEPAD),
_buttons(),
_x(0),
_y(0),
_z(0),
_rZ(0),
_rX(0),
_rY(0),
_slider1(0),
_slider2(0),
_rudder(0),
_throttle(0),
_accelerator(0),
_brake(0),
_steering(0),
_hat1(0),
_hat2(0),
_hat3(0),
_hat4(0),
_autoReport(true),
_buttonCount(0),
_hatSwitchCount(0),
_includeXAxis(true),
_includeYAxis(true),
_includeZAxis(true),
_includeRxAxis(true),
_includeRyAxis(true),
_includeRzAxis(true),
_includeSlider1(true),
_includeSlider2(true),
_includeRudder(false),
_includeThrottle(false),
_includeAccelerator(false),
_includeBrake(false),
_includeSteering(false),
hid(0)
{
this->resetButtons();
this->deviceName = deviceName;
this->deviceManufacturer = deviceManufacturer;
this->batteryLevel = batteryLevel;
this->connectionStatus = new BleConnectionStatus();
}
void BleGamepad::resetButtons() {
memset(&_buttons,0,sizeof(_buttons));
memset(&_includeSpecialButton,0,sizeof(_includeSpecialButton));
}
void BleGamepad::setControllerType(uint8_t controllerType){
_controllerType = controllerType;
}
void BleGamepad::begin(uint16_t buttonCount, uint8_t hatSwitchCount, bool includeStart, bool includeSelect, bool includeMenu, bool includeHome, bool includeBack, bool includeVolumeInc, bool includeVolumeDec, bool includeVolumeMute, bool includeXAxis, bool includeYAxis, bool includeZAxis, bool includeRzAxis, bool includeRxAxis, bool includeRyAxis, bool includeSlider1, bool includeSlider2, bool includeRudder, bool includeThrottle, bool includeAccelerator, bool includeBrake, bool includeSteering)
{
_buttonCount = buttonCount;
_hatSwitchCount = hatSwitchCount;
_includeSpecialButton[0] = includeStart;
_includeSpecialButton[1] = includeSelect;
_includeSpecialButton[2] = includeMenu;
_includeSpecialButton[3] = includeHome;
_includeSpecialButton[4] = includeBack;
_includeSpecialButton[5] = includeVolumeInc;
_includeSpecialButton[6] = includeVolumeDec;
_includeSpecialButton[7] = includeVolumeMute;
_includeXAxis = includeXAxis;
_includeYAxis = includeYAxis;
_includeZAxis = includeZAxis;
_includeRzAxis = includeRzAxis;
_includeRxAxis = includeRxAxis;
_includeRyAxis = includeRyAxis;
_includeSlider1 = includeSlider1;
_includeSlider2 = includeSlider2;
_includeRudder = includeRudder;
_includeThrottle = includeThrottle;
_includeAccelerator = includeAccelerator;
_includeBrake = includeBrake;
_includeSteering = includeSteering;
for (int i = 0; i < 7; i++)
{
if (_includeSpecialButton[i]) { _specialButtonCount++; }
}
uint8_t axisCount = 0;
if (_includeXAxis){ axisCount++; }
if (_includeYAxis){ axisCount++; }
if (_includeZAxis){ axisCount++; }
if (_includeRzAxis){ axisCount++; }
if (_includeRxAxis){ axisCount++; }
if (_includeRyAxis){ axisCount++; }
if (_includeSlider1){ axisCount++; }
if (_includeSlider2){ axisCount++; }
uint8_t simulationCount = 0;
if (_includeRudder){ simulationCount++; }
if (_includeThrottle){ simulationCount++; }
if (_includeAccelerator){ simulationCount++; }
if (_includeBrake){ simulationCount++; }
if (_includeSteering){ simulationCount++; }
uint8_t buttonPaddingBits = 8 - (_buttonCount % 8);
if(buttonPaddingBits == 8){buttonPaddingBits = 0;}
uint8_t specialButtonPaddingBits = 8 - (_specialButtonCount % 8);
if(specialButtonPaddingBits == 8){specialButtonPaddingBits = 0;}
uint8_t numOfAxisBytes = axisCount * 2;
uint8_t numOfSimulationBytes = simulationCount * 2;
numOfButtonBytes = _buttonCount / 8;
if( buttonPaddingBits > 0){numOfButtonBytes++;}
uint8_t numOfSpecialButtonBytes = _specialButtonCount / 8;
if( specialButtonPaddingBits > 0){numOfSpecialButtonBytes++;}
reportSize = numOfButtonBytes + numOfSpecialButtonBytes + numOfAxisBytes + numOfSimulationBytes + _hatSwitchCount;
// USAGE_PAGE (Generic Desktop)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// USAGE (Joystick - 0x04; Gamepad - 0x05; Multi-axis Controller - 0x08)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = _controllerType;
// COLLECTION (Application)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xa1;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_ID (Default: 3)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x85;
tempHidReportDescriptor[hidReportDescriptorSize++] = _hidReportId;
if (_buttonCount > 0){
// USAGE_PAGE (Button)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
// LOGICAL_MINIMUM (0)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// LOGICAL_MAXIMUM (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_SIZE (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// USAGE_MINIMUM (Button 1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x19;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// USAGE_MAXIMUM (Up to 128 buttons possible)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x29;
tempHidReportDescriptor[hidReportDescriptorSize++] = _buttonCount;
// REPORT_COUNT (# of buttons)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = _buttonCount;
// UNIT_EXPONENT (0)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x55;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// UNIT (None)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x65;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// INPUT (Data,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
if (buttonPaddingBits > 0) {
// REPORT_SIZE (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_COUNT (# of padding bits)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = buttonPaddingBits;
// INPUT (Const,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03;
} // Padding Bits Needed
} // Buttons
if (_specialButtonCount > 0){
// LOGICAL_MINIMUM (0)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// LOGICAL_MAXIMUM (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_SIZE (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
if (_includeSpecialButton[0] || _includeSpecialButton[1] || _includeSpecialButton[2]){
// USAGE_PAGE (Generic Desktop)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_COUNT
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = (int)_includeSpecialButton[0] + (int)_includeSpecialButton[1] + (int)_includeSpecialButton[2];
if (_includeSpecialButton[0]){
// USAGE (Start)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x3D;
}
if (_includeSpecialButton[1]){
// USAGE (Select)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x3E;
}
if (_includeSpecialButton[2]){
// USAGE (App Menu)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x86;
}
// INPUT (Data,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}
if (_includeSpecialButton[3] || _includeSpecialButton[4] || _includeSpecialButton[5] || _includeSpecialButton[6] || _includeSpecialButton[7]){
// USAGE_PAGE (Consumer Page)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x0C;
// REPORT_COUNT
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = (int)_includeSpecialButton[3] + (int)_includeSpecialButton[4] + (int)_includeSpecialButton[5] + (int)_includeSpecialButton[6] + (int)_includeSpecialButton[7];
if (_includeSpecialButton[3])
{
// USAGE (Home)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x223;
}
if (_includeSpecialButton[4])
{
// USAGE (Back)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x224;
}
if (_includeSpecialButton[5])
{
// USAGE (Volume Increment)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xE9;
}
if (_includeSpecialButton[6])
{
// USAGE (Volume Decrement)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xEA;
}
if (_includeSpecialButton[7])
{
// USAGE (Mute)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xE2;
}
// INPUT (Data,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
}
if (specialButtonPaddingBits > 0) {
// REPORT_SIZE (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// REPORT_COUNT (# of padding bits)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = specialButtonPaddingBits;
// INPUT (Const,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x03;
} // Padding Bits Needed
} // Special Buttons
if (axisCount > 0) {
// USAGE_PAGE (Generic Desktop)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// USAGE (Pointer)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// LOGICAL_MINIMUM (-32767)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x16;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x80;
// LOGICAL_MAXIMUM (+32767)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x26;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x7F;
// REPORT_SIZE (16)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10;
// REPORT_COUNT (axisCount)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = axisCount;
// COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
if (_includeXAxis == true) {
// USAGE (X)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x30;
}
if (_includeYAxis == true) {
// USAGE (Y)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x31;
}
if (_includeZAxis == true) {
// USAGE (Z)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x32;
}
if (_includeRzAxis == true) {
// USAGE (Rz)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35;
}
if (_includeRxAxis == true) {
// USAGE (Rx)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x33;
}
if (_includeRyAxis == true) {
// USAGE (Ry)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x34;
}
if (_includeSlider1 == true) {
// USAGE (Slider)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x36;
}
if (_includeSlider2 == true) {
// USAGE (Slider)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x36;
}
// INPUT (Data,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
// END_COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
} // X, Y, Z, Rx, Ry, and Rz Axis
if (simulationCount > 0) {
// USAGE_PAGE (Simulation Controls)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x05;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
// LOGICAL_MINIMUM (-32767)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x16;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x80;
// LOGICAL_MAXIMUM (+32767)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x26;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xFF;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x7F;
// REPORT_SIZE (16)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x10;
// REPORT_COUNT (simulationCount)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = simulationCount;
// COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
if (includeRudder == true) {
// USAGE (Rudder)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBA;
}
if (includeThrottle == true) {
// USAGE (Throttle)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xBB;
}
if (includeAccelerator == true) {
// USAGE (Accelerator)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC4;
}
if (includeBrake == true) {
// USAGE (Brake)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC5;
}
if (includeSteering == true) {
// USAGE (Steering)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x09;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xC8;
}
// INPUT (Data,Var,Abs)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x02;
// END_COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
} // Simulation Controls
if(_hatSwitchCount > 0){
// COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xA1;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// USAGE_PAGE (Generic Desktop)
tempHidReportDescriptor[hidReportDescriptorSize++] = USAGE_PAGE(1);
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// USAGE (Hat Switch)
for(int currentHatIndex = 0 ; currentHatIndex < _hatSwitchCount ; currentHatIndex++){
tempHidReportDescriptor[hidReportDescriptorSize++] = USAGE(1);
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x39;
}
// Logical Min (1)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x15;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// Logical Max (8)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x25;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x08;
// Physical Min (0)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x35;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x00;
// Physical Max (315)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x46;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x3B;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x01;
// Unit (SI Rot : Ang Pos)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x65;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x12;
// Report Size (8)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x75;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x08;
// Report Count (4)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x95;
tempHidReportDescriptor[hidReportDescriptorSize++] = _hatSwitchCount;
// Input (Data, Variable, Absolute)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x81;
tempHidReportDescriptor[hidReportDescriptorSize++] = 0x42;
// END_COLLECTION (Physical)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
}
// END_COLLECTION (Application)
tempHidReportDescriptor[hidReportDescriptorSize++] = 0xc0;
xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL);
}
void BleGamepad::end(void)
{
}
void BleGamepad::setAxes(int16_t x, int16_t y, int16_t z, int16_t rZ, int16_t rX, int16_t rY, int16_t slider1, int16_t slider2, signed char hat1, signed char hat2, signed char hat3, signed char hat4)
{
if(x == -32768) { x = -32767; }
if(y == -32768) { y = -32767; }
if(z == -32768) { z = -32767; }
if(rZ == -32768) { rZ = -32767; }
if(rX == -32768) { rX = -32767; }
if(rY == -32768) { rY = -32767; }
if(slider1 == -32768) { slider1 = -32767; }
if(slider2 == -32768) { slider2 = -32767; }
_x = x;
_y = y;
_z = z;
_rZ = rZ;
_rX = rX;
_rY = rY;
_slider1 = slider1;
_slider2 = slider2;
_hat1 = hat1;
_hat2 = hat2;
_hat3 = hat3;
_hat4 = hat4;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSimulationControls(int16_t rudder, int16_t throttle, int16_t accelerator, int16_t brake, int16_t steering)
{
if(rudder == -32768) { rudder = -32767; }
if(throttle == -32768) { throttle = -32767; }
if(accelerator == -32768) { accelerator = -32767; }
if(brake == -32768) { brake = -32767; }
if(steering == -32768) { steering = -32767; }
_rudder = rudder;
_throttle = throttle;
_accelerator = accelerator;
_brake = brake;
_steering = steering;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHats(signed char hat1, signed char hat2, signed char hat3, signed char hat4)
{
_hat1 = hat1;
_hat2 = hat2;
_hat3 = hat3;
_hat4 = hat4;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSliders(int16_t slider1, int16_t slider2)
{
if(slider1 == -32768) { slider1 = -32767; }
if(slider2 == -32768) { slider2 = -32767; }
_slider1 = slider1;
_slider2 = slider2;
if(_autoReport){ sendReport(); }
}
void BleGamepad::sendReport(void)
{
if (this->isConnected())
{
uint8_t currentReportIndex = 0;
uint8_t m[reportSize];
memset(&m,0,sizeof(m));
memcpy(&m, &_buttons, sizeof(_buttons));
currentReportIndex+=numOfButtonBytes;
if(_specialButtonCount > 0) { m[currentReportIndex++] = _specialButtons; }
if(_includeXAxis){ m[currentReportIndex++] = _x; m[currentReportIndex++] = (_x >> 8); }
if(_includeYAxis){ m[currentReportIndex++] = _y; m[currentReportIndex++] = (_y >> 8); }
if(_includeZAxis){ m[currentReportIndex++] = _z; m[currentReportIndex++] = (_z >> 8); }
if(_includeRzAxis){ m[currentReportIndex++] = _rZ; m[currentReportIndex++] = (_rZ >> 8); }
if(_includeRxAxis){ m[currentReportIndex++] = _rX; m[currentReportIndex++] = (_rX >> 8); }
if(_includeRyAxis){ m[currentReportIndex++] = _rY; m[currentReportIndex++] = (_rY >> 8); }
if(_includeSlider1){ m[currentReportIndex++] = _slider1; m[currentReportIndex++] = (_slider1 >> 8); }
if(_includeSlider2){ m[currentReportIndex++] = _slider2; m[currentReportIndex++] = (_slider2 >> 8); }
if(_includeRudder){ m[currentReportIndex++] = _rudder; m[currentReportIndex++] = (_rudder >> 8); }
if(_includeThrottle){ m[currentReportIndex++] = _throttle; m[currentReportIndex++] = (_throttle >> 8); }
if(_includeAccelerator){ m[currentReportIndex++] = _accelerator; m[currentReportIndex++] = (_accelerator >> 8); }
if(_includeBrake){ m[currentReportIndex++] = _brake; m[currentReportIndex++] = (_brake >> 8); }
if(_includeSteering){ m[currentReportIndex++] = _steering; m[currentReportIndex++] = (_steering >> 8); }
if(_hatSwitchCount > 0)
{
signed char hats[4];
hats[0] = _hat1;
hats[1] = _hat2;
hats[2] = _hat3;
hats[3] = _hat4;
for(int currentHatIndex = _hatSwitchCount -1 ; currentHatIndex >= 0 ; currentHatIndex--)
{
m[currentReportIndex++] = hats[currentHatIndex];
}
}
this->inputGamepad->setValue(m, sizeof(m));
this->inputGamepad->notify();
}
}
void BleGamepad::press(uint8_t b)
{
uint8_t index = (b-1) / 8;
uint8_t bit = (b-1) % 8;
uint8_t bitmask = (1 << bit);
uint8_t result = _buttons[index] | bitmask;
if (result != _buttons[index])
{
_buttons[index] = result;
}
if(_autoReport){ sendReport(); }
}
void BleGamepad::release(uint8_t b)
{
uint8_t index = (b-1) / 8;
uint8_t bit = (b-1) % 8;
uint8_t bitmask = (1 << bit);
uint64_t result = _buttons[index] & ~bitmask;
if (result != _buttons[index])
{
_buttons[index] = result;
}
if(_autoReport){ sendReport(); }
}
uint8_t BleGamepad::specialButtonBitPosition(uint8_t b)
{
uint8_t bit = 0;
for (int i = 0; i < b; i++)
{
if(_includeSpecialButton[i])
bit++;
}
return bit;
}
void BleGamepad::pressSpecialButton(uint8_t b)
{
uint8_t button = specialButtonBitPosition(b);
uint8_t bit = button % 8;
uint8_t bitmask = (1 << bit);
uint64_t result = _specialButtons | bitmask;
if (result != _specialButtons)
{
_specialButtons = result;
}
if(_autoReport){ sendReport(); }
}
void BleGamepad::releaseSpecialButton(uint8_t b)
{
uint8_t button = specialButtonBitPosition(b);
uint8_t bit = button % 8;
uint8_t bitmask = (1 << bit);
uint64_t result = _specialButtons & ~bitmask;
if (result != _specialButtons)
{
_specialButtons = result;
}
if(_autoReport){ sendReport(); }
}
void BleGamepad::setLeftThumb(int16_t x, int16_t y)
{
if(x == -32768) { x = -32767; }
if(y == -32768) { y = -32767; }
_x = x;
_y = y;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRightThumb(int16_t z, int16_t rZ)
{
if(z == -32768) { z = -32767; }
if(rZ == -32768) { rZ = -32767; }
_z = z;
_rZ = rZ;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setLeftTrigger(int16_t rX)
{
if(rX == -32768) {rX = -32767; }
_rX = rX;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRightTrigger(int16_t rY)
{
if(rY == -32768) {rY = -32767; }
_rY = rY;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setTriggers(int16_t rX, int16_t rY)
{
if(rX == -32768) {rX = -32767; }
if(rY == -32768) {rY = -32767; }
_rX = rX;
_rY = rY;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHat(signed char hat)
{
_hat1 = hat;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHat1(signed char hat1)
{
_hat1 = hat1;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHat2(signed char hat2)
{
_hat2 = hat2;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHat3(signed char hat3)
{
_hat3 = hat3;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setHat4(signed char hat4)
{
_hat4 = hat4;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setX(int16_t x)
{
if(x == -32768) { x = -32767; }
_x = x;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setY(int16_t y)
{
if(y == -32768) { y = -32767; }
_y = y;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setZ(int16_t z)
{
if(z == -32768) { z = -32767; }
_z = z;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRZ(int16_t rZ)
{
if(rZ == -32768) { rZ = -32767; }
_rZ = rZ;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRX(int16_t rX)
{
if(rX == -32768) { rX = -32767; }
_rX = rX;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRY(int16_t rY)
{
if(rY == -32768) { rY = -32767; }
_rY = rY;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSlider(int16_t slider)
{
if(slider == -32768) { slider = -32767; }
_slider1 = slider;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSlider1(int16_t slider1)
{
if(slider1 == -32768) { slider1 = -32767; }
_slider1 = slider1;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSlider2(int16_t slider2)
{
if(slider2 == -32768) { slider2 = -32767; }
_slider2 = slider2;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setRudder(int16_t rudder)
{
if(rudder == -32768) { rudder = -32767; }
_rudder = rudder;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setThrottle(int16_t throttle)
{
if(throttle == -32768) { throttle = -32767; }
_throttle = throttle;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setAccelerator(int16_t accelerator)
{
if(accelerator == -32768) { accelerator = -32767; }
_accelerator = accelerator;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setBrake(int16_t brake)
{
if(brake == -32768) { brake = -32767; }
_brake = brake;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setSteering(int16_t steering)
{
if(steering == -32768) { steering = -32767; }
_steering = steering;
if(_autoReport){ sendReport(); }
}
void BleGamepad::setAutoReport(bool autoReport)
{
_autoReport = autoReport;
}
bool BleGamepad::isPressed(uint8_t b)
{
uint8_t index = (b-1) / 8;
uint8_t bit = (b-1) % 8;
uint8_t bitmask = (1 << bit);
if ((bitmask & _buttons[index]) > 0)
return true;
return false;
}
bool BleGamepad::isConnected(void)
{
return this->connectionStatus->connected;
}
void BleGamepad::setBatteryLevel(uint8_t level)
{
this->batteryLevel = level;
if (hid != 0)
this->hid->setBatteryLevel(this->batteryLevel);
}
void BleGamepad::taskServer(void* pvParameter)
{
BleGamepad* BleGamepadInstance = (BleGamepad *) pvParameter; //static_cast<BleGamepad *>(pvParameter);
NimBLEDevice::init(BleGamepadInstance->deviceName);
NimBLEServer *pServer = NimBLEDevice::createServer();
pServer->setCallbacks(BleGamepadInstance->connectionStatus);
BleGamepadInstance->hid = new NimBLEHIDDevice(pServer);
BleGamepadInstance->inputGamepad = BleGamepadInstance->hid->inputReport(_hidReportId); // <-- input REPORTID from report map
BleGamepadInstance->connectionStatus->inputGamepad = BleGamepadInstance->inputGamepad;
BleGamepadInstance->hid->manufacturer()->setValue(BleGamepadInstance->deviceManufacturer);
BleGamepadInstance->hid->pnp(0x01,0x02e5,0xabbb,0x0110);
BleGamepadInstance->hid->hidInfo(0x00,0x01);
NimBLESecurity *pSecurity = new NimBLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND);
uint8_t *customHidReportDescriptor = new uint8_t[hidReportDescriptorSize];
memcpy(customHidReportDescriptor, tempHidReportDescriptor, hidReportDescriptorSize);
BleGamepadInstance->hid->reportMap((uint8_t*)customHidReportDescriptor, hidReportDescriptorSize);
BleGamepadInstance->hid->startServices();
BleGamepadInstance->onStarted(pServer);
NimBLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->setAppearance(HID_GAMEPAD);
pAdvertising->addServiceUUID(BleGamepadInstance->hid->hidService()->getUUID());
pAdvertising->start();
BleGamepadInstance->hid->setBatteryLevel(BleGamepadInstance->batteryLevel);
ESP_LOGD(LOG_TAG, "Advertising started!");
vTaskDelay(portMAX_DELAY); //delay(portMAX_DELAY);
}