|
|
@@ -0,0 +1,172 @@ |
|
|
include <BLEDevice.h> |
|
|
#include <BLEUtils.h> |
|
|
#include <BLEServer.h> |
|
|
#include "BLE2902.h" |
|
|
#include "BLEHIDDevice.h" |
|
|
#include "HIDTypes.h" |
|
|
#include "HIDKeyboardTypes.h" |
|
|
#include <driver/adc.h> |
|
|
|
|
|
BLEHIDDevice* hid; |
|
|
BLECharacteristic* input; |
|
|
BLECharacteristic* output; |
|
|
|
|
|
uint8_t buttons = 0; |
|
|
uint8_t button1 = 0; |
|
|
uint8_t button2 = 0; |
|
|
uint8_t button3 = 0; |
|
|
bool connected = false; |
|
|
|
|
|
class MyCallbacks : public BLEServerCallbacks { |
|
|
void onConnect(BLEServer* pServer){ |
|
|
connected = true; |
|
|
BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); |
|
|
desc->setNotifications(true); |
|
|
} |
|
|
|
|
|
void onDisconnect(BLEServer* pServer){ |
|
|
connected = false; |
|
|
BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); |
|
|
desc->setNotifications(false); |
|
|
} |
|
|
}; |
|
|
|
|
|
/* |
|
|
* This callback is connect with output report. In keyboard output report report special keys changes, like CAPSLOCK, NUMLOCK |
|
|
* We can add digital pins with LED to show status |
|
|
* bit 0 - NUM LOCK |
|
|
* bit 1 - CAPS LOCK |
|
|
* bit 2 - SCROLL LOCK |
|
|
*/ |
|
|
class MyOutputCallbacks : public BLECharacteristicCallbacks { |
|
|
void onWrite(BLECharacteristic* me){ |
|
|
uint8_t* value = (uint8_t*)(me->getValue().c_str()); |
|
|
ESP_LOGI(LOG_TAG, "special keys: %d", *value); |
|
|
} |
|
|
}; |
|
|
|
|
|
void taskServer(void*){ |
|
|
|
|
|
|
|
|
BLEDevice::init("Backpack-MeowMeow"); |
|
|
BLEServer *pServer = BLEDevice::createServer(); |
|
|
pServer->setCallbacks(new MyCallbacks()); |
|
|
|
|
|
hid = new BLEHIDDevice(pServer); |
|
|
input = hid->inputReport(1); // <-- input REPORTID from report map |
|
|
output = hid->outputReport(1); // <-- output REPORTID from report map |
|
|
|
|
|
output->setCallbacks(new MyOutputCallbacks()); |
|
|
|
|
|
std::string name = "ElectronicCats"; |
|
|
hid->manufacturer()->setValue(name); |
|
|
|
|
|
hid->pnp(0x02, 0xe502, 0xa111, 0x0210); |
|
|
hid->hidInfo(0x00,0x02); |
|
|
|
|
|
BLESecurity *pSecurity = new BLESecurity(); |
|
|
// pSecurity->setKeySize(); |
|
|
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); |
|
|
|
|
|
const uint8_t report[] = { |
|
|
USAGE_PAGE(1), 0x01, // Generic Desktop Ctrls |
|
|
USAGE(1), 0x06, // Keyboard |
|
|
COLLECTION(1), 0x01, // Application |
|
|
REPORT_ID(1), 0x01, // Report ID (1) |
|
|
USAGE_PAGE(1), 0x07, // Kbrd/Keypad |
|
|
USAGE_MINIMUM(1), 0xE0, |
|
|
USAGE_MAXIMUM(1), 0xE7, |
|
|
LOGICAL_MINIMUM(1), 0x00, |
|
|
LOGICAL_MAXIMUM(1), 0x01, |
|
|
REPORT_SIZE(1), 0x01, // 1 byte (Modifier) |
|
|
REPORT_COUNT(1), 0x08, |
|
|
HIDINPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position |
|
|
REPORT_COUNT(1), 0x01, // 1 byte (Reserved) |
|
|
REPORT_SIZE(1), 0x08, |
|
|
HIDINPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position |
|
|
REPORT_COUNT(1), 0x06, // 6 bytes (Keys) |
|
|
REPORT_SIZE(1), 0x08, |
|
|
LOGICAL_MINIMUM(1), 0x00, |
|
|
LOGICAL_MAXIMUM(1), 0x65, // 101 keys |
|
|
USAGE_MINIMUM(1), 0x00, |
|
|
USAGE_MAXIMUM(1), 0x65, |
|
|
HIDINPUT(1), 0x00, // Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position |
|
|
REPORT_COUNT(1), 0x05, // 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana) |
|
|
REPORT_SIZE(1), 0x01, |
|
|
USAGE_PAGE(1), 0x08, // LEDs |
|
|
USAGE_MINIMUM(1), 0x01, // Num Lock |
|
|
USAGE_MAXIMUM(1), 0x05, // Kana |
|
|
HIDOUTPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile |
|
|
REPORT_COUNT(1), 0x01, // 3 bits (Padding) |
|
|
REPORT_SIZE(1), 0x03, |
|
|
HIDOUTPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile |
|
|
END_COLLECTION(0) |
|
|
}; |
|
|
|
|
|
hid->reportMap((uint8_t*)report, sizeof(report)); |
|
|
hid->startServices(); |
|
|
|
|
|
BLEAdvertising *pAdvertising = pServer->getAdvertising(); |
|
|
pAdvertising->setAppearance(HID_KEYBOARD); |
|
|
pAdvertising->addServiceUUID(hid->hidService()->getUUID()); |
|
|
pAdvertising->start(); |
|
|
hid->setBatteryLevel(7); |
|
|
|
|
|
ESP_LOGD(LOG_TAG, "Advertising started!"); |
|
|
delay(portMAX_DELAY); |
|
|
|
|
|
}; |
|
|
|
|
|
void setup() { |
|
|
Serial.begin(115200); |
|
|
Serial.println("Starting BLE work!"); |
|
|
|
|
|
pinMode(12, INPUT_PULLDOWN); |
|
|
attachInterrupt(digitalPinToInterrupt(12), clickNumLock, CHANGE); // Num Lock |
|
|
pinMode(14, INPUT_PULLDOWN); |
|
|
attachInterrupt(digitalPinToInterrupt(13), clickCapsLock, CHANGE); // Caps Lock |
|
|
pinMode(32, INPUT_PULLDOWN); |
|
|
attachInterrupt(digitalPinToInterrupt(32), clickScrollLock, CHANGE); // Scroll Lock |
|
|
|
|
|
xTaskCreate(taskServer, "server", 20000, NULL, 5, NULL); |
|
|
} |
|
|
|
|
|
void loop() { |
|
|
|
|
|
if(connected){ |
|
|
|
|
|
vTaskDelay(5000); |
|
|
const char* hello = "Hello world from esp32 hid keyboard!!!\n"; |
|
|
|
|
|
while(*hello){ |
|
|
KEYMAP map = keymap[(uint8_t)*hello]; |
|
|
Serial.println(buttons); |
|
|
uint8_t msg[] = {map.modifier || buttons, 0x0, map.usage, 0x0,0x0,0x0,0x0,0x0}; |
|
|
input->setValue(msg,sizeof(msg)); |
|
|
input->notify(); |
|
|
hello++; |
|
|
uint8_t msg1[] = {0x0, 0x0, 0x0, 0x0,0x0,0x0,0x0,0x0}; |
|
|
|
|
|
input->setValue(msg1,sizeof(msg1)); |
|
|
input->notify(); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
delay(50); |
|
|
} |
|
|
|
|
|
IRAM_ATTR void clickNumLock(){ |
|
|
button1 = buttons&&0x01; |
|
|
button1 != button1; |
|
|
buttons = button1<<0; |
|
|
} |
|
|
IRAM_ATTR void clickCapsLock(){ |
|
|
button2 = buttons&&0x02; |
|
|
button2 != button2; |
|
|
buttons = button2<<1; |
|
|
} |
|
|
IRAM_ATTR void clickScrollLock(){ |
|
|
button3 = buttons&&0x04; |
|
|
button3 != button3; |
|
|
buttons = button3<<2; |
|
|
} |