Skip to content

Commit 57d0ae6

Browse files
authored
Allow forced pairing and removing of bonds
A much requested feature to work around hosts aggressively connecting to gamepad unwantedly. Example provided
1 parent 7832309 commit 57d0ae6

File tree

4 files changed

+194
-10
lines changed

4 files changed

+194
-10
lines changed

BleConnectionStatus.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "BleConnectionStatus.h"
2+
#include <NimBLEDevice.h>
23

34
BleConnectionStatus::BleConnectionStatus(void)
45
{
@@ -7,14 +8,28 @@ BleConnectionStatus::BleConnectionStatus(void)
78
void BleConnectionStatus::onConnect(NimBLEServer *pServer, NimBLEConnInfo& connInfo)
89
{
910
pServer->updateConnParams(connInfo.getConnHandle(), 6, 7, 0, 600);
11+
12+
//NimBLEAddress addr = connInfo.getAddress();
13+
//Serial.print("onConnect - Connected from: ");
14+
//Serial.println(addr.toString().c_str());
1015
}
1116

1217
void BleConnectionStatus::onDisconnect(NimBLEServer* pServer, NimBLEConnInfo& connInfo, int reason)
1318
{
19+
//NimBLEAddress addr = connInfo.getAddress();
20+
//Serial.print("onDisconnect - Disconnected from: ");
21+
//Serial.println(addr.toString().c_str());
22+
1423
this->connected = false;
24+
delay(500);
25+
NimBLEDevice::startAdvertising(); // Restart advertising
1526
}
1627

1728
void BleConnectionStatus::onAuthenticationComplete(NimBLEConnInfo& connInfo)
1829
{
30+
//NimBLEAddress addr = connInfo.getAddress();
31+
//Serial.print("onAuthenticationComplete - Connected from: ");
32+
//Serial.println(addr.toString().c_str());
33+
1934
this->connected = true;
2035
}

BleGamepad.cpp

Lines changed: 109 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,30 +1399,129 @@ void BleGamepad::setBatteryLevel(uint8_t level)
13991399
}
14001400
}
14011401

1402-
bool BleGamepad::isOutputReceived(){
1403-
if(enableOutputReport && outputReceiver){
1404-
if(this->outputReceiver->outputFlag){
1402+
bool BleGamepad::isOutputReceived()
1403+
{
1404+
if(enableOutputReport && outputReceiver)
1405+
{
1406+
if(this->outputReceiver->outputFlag)
1407+
{
14051408
this->outputReceiver->outputFlag=false; // Clear Flag
14061409
return true;
14071410
}
14081411
}
14091412
return false;
14101413
}
1411-
uint8_t* BleGamepad::getOutputBuffer(){
1412-
if(enableOutputReport && outputReceiver){
1414+
1415+
uint8_t* BleGamepad::getOutputBuffer()
1416+
{
1417+
if(enableOutputReport && outputReceiver)
1418+
{
14131419
memcpy(outputBackupBuffer, outputReceiver->outputBuffer, outputReportLength); // Creating a backup to avoid buffer being overwritten while processing data
14141420
return outputBackupBuffer;
14151421
}
14161422
return nullptr;
14171423
}
1424+
1425+
bool BleGamepad::deleteAllBonds(bool resetBoard)
1426+
{
1427+
bool success = false;
1428+
1429+
NimBLEDevice::deleteAllBonds();
1430+
success = true;
1431+
delay(500);
1432+
1433+
if (resetBoard)
1434+
{
1435+
ESP.restart();
1436+
}
1437+
1438+
return success; // Returns false if all bonds are not deleted
1439+
}
1440+
1441+
bool BleGamepad::deleteBond(bool resetBoard)
1442+
{
1443+
bool success = false;
1444+
1445+
NimBLEServer* server = NimBLEDevice::getServer();
1446+
1447+
if (server)
1448+
{
1449+
NimBLEConnInfo info = server->getPeerInfo(0);
1450+
NimBLEAddress address = info.getAddress();
1451+
1452+
success = NimBLEDevice::deleteBond(address);
1453+
1454+
delay(500);
1455+
1456+
if (resetBoard)
1457+
{
1458+
ESP.restart();
1459+
}
1460+
}
1461+
return success; // Returns false if current bond is not deleted
1462+
}
1463+
1464+
bool BleGamepad::enterPairingMode()
1465+
{
1466+
NimBLEServer* server = NimBLEDevice::getServer();
1467+
1468+
if (server)
1469+
{
1470+
//Serial.println("Entered pairing mode");
1471+
1472+
// Get current connection information and address
1473+
NimBLEConnInfo currentConnInfo = server->getPeerInfo(0);
1474+
NimBLEAddress currentAddress = currentConnInfo.getAddress();
1475+
//Serial.print("Current Address is: ");
1476+
//Serial.println(currentAddress.toString().c_str());
1477+
1478+
// Disconnect from current connection
1479+
for (uint16_t connHandle : server->getPeerDevices())
1480+
{
1481+
server->disconnect(connHandle); // Disconnect the client
1482+
//Serial.println("Disconnected from client");
1483+
delay(1000);
1484+
}
1485+
1486+
bool connectedToOldDevice = true;
1487+
1488+
// While connected to old device, keep allowing to connect new new devices
1489+
while(connectedToOldDevice)
1490+
{
1491+
//Serial.println("While loop entered");
1492+
delay(10); // Needs a delay to work - do not remove!
1493+
1494+
if(this->isConnected())
1495+
{
1496+
NimBLEConnInfo newConnInfo = server->getPeerInfo(0);
1497+
NimBLEAddress newAddress = newConnInfo.getAddress();
1498+
1499+
//Serial.print("Current Address is: ");
1500+
//Serial.println(newAddress.toString().c_str());
1501+
1502+
// Block specific MAC address
1503+
if (newAddress == currentAddress)
1504+
{
1505+
//Serial.println("Addresses match - blocking");
1506+
server->disconnect(newConnInfo.getConnHandle());
1507+
delay(500);
1508+
}
1509+
else
1510+
{
1511+
//Serial.println("New device connected");
1512+
connectedToOldDevice = false;
1513+
return true;
1514+
}
1515+
}
1516+
}
1517+
return false; // Might want to adjust this function to stay in pairing mode for a while, and then return false after a while if no other device pairs with it
1518+
}
1519+
}
1520+
1521+
14181522
void BleGamepad::taskServer(void *pvParameter)
14191523
{
14201524
BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter; // static_cast<BleGamepad *>(pvParameter);
1421-
1422-
// Use the procedure below to set a custom Bluetooth MAC address
1423-
// 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
1424-
//uint8_t newMACAddress[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - 0x02};
1425-
//esp_base_mac_addr_set(&newMACAddress[0]); // Set new MAC address
14261525

14271526
NimBLEDevice::init(BleGamepadInstance->deviceName);
14281527
NimBLEServer *pServer = NimBLEDevice::createServer();

BleGamepad.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class BleGamepad
113113
std::string deviceName;
114114
bool isOutputReceived();
115115
uint8_t* getOutputBuffer();
116+
bool deleteBond(bool resetBoard = false);
117+
bool deleteAllBonds(bool resetBoard = false);
118+
bool enterPairingMode();
116119

117120
protected:
118121
virtual void onStarted(NimBLEServer *pServer){};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* A simple sketch that, upon a button press, disconnects from an aggressive client
3+
* until a new client connects to the gamepad
4+
*
5+
* If it finds another client that's already paired, it will connect to that
6+
*
7+
* If it doesn't find another paired device, it will allow you to pair a new one
8+
*
9+
* If you want a more permanent solution, instead use bleGamepad.deleteBond()
10+
* which will delete the bond for the currently connected client and allow other
11+
* clients to connect to it
12+
*
13+
* Use bleGamepad.deletAllBonds() to delete all bonds from the gamepad
14+
*
15+
* After deleting bonds, it is best to unpair them from the client device such
16+
* as your phone or PC otherwise the gamepad may briefly connect while searching
17+
*
18+
* The deleteBond and deletAllBonds functions can optionalayy reset the gamepad with
19+
* deletAllBonds(true) or deleteBond(true), although it shouldn't be needed
20+
* as the advertising should now start again after a client is disconnected
21+
*
22+
* They all return a boolean for success or failure if wanted
23+
*/
24+
25+
#include <Arduino.h>
26+
#include <BleGamepad.h> // https://github.com/lemmingDev/ESP32-BLE-Gamepad
27+
28+
#define DISCONNECTPIN 0 // Pin disconnect button is attached to
29+
30+
BleGamepad bleGamepad;
31+
32+
void setup()
33+
{
34+
Serial.begin(115200);
35+
pinMode(DISCONNECTPIN, INPUT_PULLUP);
36+
bleGamepad.begin();
37+
}
38+
39+
void loop()
40+
{
41+
if (bleGamepad.isConnected())
42+
{
43+
// Enter forced pairing mode
44+
// It repeatedly disconnects from currently connected device until a new device is paired
45+
// Returns true if a new device is connected
46+
// For now, enters an endless loop if no new device found
47+
// Simply reset device to have it revert to previous behaviour
48+
if (digitalRead(DISCONNECTPIN) == LOW) // On my board, pin 0 is LOW for pressed
49+
{
50+
bool pairingResult = bleGamepad.enterPairingMode();
51+
52+
if(pairingResult)
53+
{
54+
Serial.println("New device paired successfully");
55+
}
56+
else
57+
{
58+
Serial.println("No new device paired");
59+
}
60+
}
61+
}
62+
else
63+
{
64+
Serial.println("No device connected");
65+
delay(1000);
66+
}
67+
}

0 commit comments

Comments
 (0)