#ifndef ESP32_BLE_GAMEPAD_H #define ESP32_BLE_GAMEPAD_H #include "sdkconfig.h" #if defined(CONFIG_BT_ENABLED) #ifndef GAMEPAD_CLASS #define GAMEPAD_CLASS BleGamepad #endif #include "../common.h" #include "BLE2902.h" #include "BLEHIDDevice.h" #include "HIDKeyboardTypes.h" #include "HIDTypes.h" #include #include #include #include #include "BLECharacteristic.h" #include "BLEHIDDevice.h" #include "BleConnectionStatus.h" #if defined(CONFIG_ARDUHAL_ESP_LOG) #include "esp32-hal-log.h" #define LOG_TAG "" #else #include "esp_log.h" static const char *LOG_TAG = "BLEDevice"; #endif class BleGamepad : public AbstractGamepad { private: BleConnectionStatus *connectionStatus; BLEHIDDevice *hid; BLECharacteristic *inputGamepad[GAMEPAD_COUNT]; void rawAction(uint8_t msg[], char msgSize); static void taskServer(void *pvParameter) { BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter; // static_cast(pvParameter); BLEDevice::init(BleGamepadInstance->deviceName); BLEServer *pServer = BLEDevice::createServer(); pServer->setCallbacks(BleGamepadInstance->connectionStatus); BleGamepadInstance->hid = new BLEHIDDevice(pServer); for (int c = 0; c < GAMEPAD_COUNT; c++) { BleGamepadInstance->inputGamepad[c] = BleGamepadInstance->hid->inputReport(c); // <-- input REPORTID from report map BleGamepadInstance->connectionStatus->inputGamepad[c] = BleGamepadInstance->inputGamepad[c]; } BleGamepadInstance->hid->manufacturer()->setValue(BleGamepadInstance->deviceManufacturer); // todo: is this change required for 2 inputs??? // BleGamepadInstance->hid->pnp(0x01,0x02e5,0xabcc,0x0110); BleGamepadInstance->hid->pnp(0x02, 0x8282, 0x0132, 0x0106); BleGamepadInstance->hid->hidInfo(0x00, 0x01); BLESecurity *pSecurity = new BLESecurity(); pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); BleGamepadInstance->hid->reportMap((uint8_t *)_hidReportDescriptor, sizeof(_hidReportDescriptor)); BleGamepadInstance->hid->startServices(); BleGamepadInstance->onStarted(pServer); BLEAdvertising *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); } public: uint8_t batteryLevel; std::string deviceManufacturer; std::string deviceName; BleGamepad(std::string deviceName = "8BitDo SN30 Pro+", std::string deviceManufacturer = "8Bitdo SF30 Pro", uint8_t batteryLevel = 100) : AbstractGamepad(), hid(0) { this->deviceName = deviceName; this->deviceManufacturer = deviceManufacturer; this->batteryLevel = batteryLevel; this->connectionStatus = new BleConnectionStatus(); } virtual void begin(void) { xTaskCreate(this->taskServer, "server", 20000, (void *)this, 5, NULL); } virtual void sendHidReport(const uint8_t cIdx, const void *d, int len) { if (this->isConnected()) { this->inputGamepad[cIdx]->setValue((uint8_t *)d, len); this->inputGamepad[cIdx]->notify(); } } virtual bool isConnected(void) { return this->connectionStatus->connected; } virtual void setBatteryLevel(uint8_t level) { this->batteryLevel = level; if (hid != 0) this->hid->setBatteryLevel(this->batteryLevel); } protected: virtual void onStarted(BLEServer *pServer){}; }; #endif // CONFIG_BT_ENABLED #endif // ESP32_BLE_GAMEPAD_H