lemmingDev / ESP32-BLE-Gamepad

Bluetooth LE Gamepad library for the ESP32
Other
1.09k stars 181 forks source link

BSOD and WDF_VIOLATION error on Windows 11 after connected #198

Closed praditautama closed 1 year ago

praditautama commented 1 year ago

Hello, I am building BLE Gamepad with 0.9 inch OLED display on ESP32 DEVKITC V4 WROOM-32U, I use macOS for development.

Everything works on macOS, I can test all buttons using "Controller Lite" app from AppStore, all buttons worked. But every time I connected to Windows 11 PC, I got BSOD with WDF_VIOLATION error.

I searched for WDF_VIOLATION, It's related to bad driver mostly BT driver. Is there any chance my USB dongle doesn't support for BLE?

My PC:

Added my source code

#include <Arduino.h>

#include <Keypad.h>      // https://github.com/Chris--A/Keypad
#include <BleGamepad.h>  // https://github.com/lemmingDev/ESP32-BLE-Gamepad
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <ESP32Encoder.h>  // https://github.com/madhephaestus/ESP32Encoder

#define SCREEN_WIDTH 128     // OLED display width, in pixels
#define SCREEN_HEIGHT 64     // OLED display height, in pixels
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define BUF_SIZE 64
#define ROWS 3
#define COLS 5
uint8_t rowPins[ROWS] = { 2, 4, 13 };            // ESP32 pins used for rows      --> adjust to suit --> Pinout on board: R1, R2, R3, R4
uint8_t colPins[COLS] = { 14, 15, 16, 17, 18 };  // ESP32 pins used for columns   --> adjust to suit --> Pinout on board: Q1, Q2, Q3, Q4
uint8_t keymap[ROWS][COLS] = {
  { 1, 2, 3, 4, 5 },
  { 6, 7, 8, 9, 10 },
  { 11, 12, 13, 14, 15 }
};

uint8_t newMACAddress[] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF - 0x02 };

// Create encoder objects
ESP32Encoder encoder1;
ESP32Encoder encoder2;
ESP32Encoder encoder3;

// Variables to store the current encoder count
int32_t encoder1Count = 0;
int32_t encoder2Count = 0;
int32_t encoder3Count = 0;

BleGamepad bleGamepad("Rally Button Box", "Javasim Esports", 100);  // Shows how you can customise the device name, manufacturer name and initial battery level

Keypad customKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, ROWS, COLS);

void setup() {

  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {  // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
  delay(2000);

  printWelcomeMessage();
  delay(5000);

  // Enable the weak pull up resistors
  ESP32Encoder::useInternalWeakPullResistors = UP;

  // Attach pins to encoders
  encoder1.attachHalfQuad(5, 34);
  encoder2.attachHalfQuad(25, 26);
  encoder3.attachHalfQuad(32, 33);

  // Clear encoder counts
  encoder1.clearCount();
  encoder2.clearCount();
  encoder3.clearCount();

  // Initialise encoder counts
  encoder1Count = encoder1.getCount();
  encoder2Count = encoder2.getCount();
  encoder3Count = encoder3.getCount();

  BleGamepadConfiguration bleGamepadConfig;
  bleGamepadConfig.setButtonCount(26);
  bleGamepadConfig.setControllerType(CONTROLLER_TYPE_GAMEPAD);
  bleGamepadConfig.setWhichAxes(false, false, false, false, false, false, false, false);
  bleGamepadConfig.setAutoReport(false);  // Disable auto reports --> You then need to force HID updates with bleGamepad.sendReport()
  bleGamepadConfig.setVid(0xe502);
  bleGamepadConfig.setPid(0xabcd);

  // bleGamepadConfig.setModelNumber("1.0");
  // bleGamepadConfig.setSoftwareRevision("Software Rev 1");
  // bleGamepadConfig.setSerialNumber("9876543210");
  // bleGamepadConfig.setFirmwareRevision("2.0");
  // bleGamepadConfig.setHardwareRevision("1.7");
  bleGamepad.begin(&bleGamepadConfig);  // Begin library with default buttons/hats/axes
  // changing bleGamepadConfig after the begin function has no effect, unless you call the begin function again
  esp_base_mac_addr_set(&newMACAddress[0]); // Set new MAC address
  printConnectingMessage();
  delay(5000);
}

void loop() {
  if (bleGamepad.isConnected()) {
    printStandyMessage();
    KeypadUpdate();
    EncodersUpdate();
  } else {
    printErrorConnection();
  }
  delay(10);
}

void EncodersUpdate() {
  int32_t tempEncoderCount1 = encoder1.getCount();
  int32_t tempEncoderCount2 = encoder2.getCount();
  int32_t tempEncoderCount3 = encoder3.getCount();

  bool sendReport = false;

  if (tempEncoderCount1 != encoder1Count) {
    sendReport = true;
    Serial.println(tempEncoderCount1);
    Serial.println(encoder1Count);

    if (tempEncoderCount1 > encoder1Count) {
      bleGamepad.press(BUTTON_14);
    } else {
      bleGamepad.press(BUTTON_15);
    }
  }

  if (tempEncoderCount2 != encoder2Count) {
    sendReport = true;

    if (tempEncoderCount2 > encoder2Count) {
      bleGamepad.press(BUTTON_16);
    } else {
      bleGamepad.press(BUTTON_17);
    }
  }

  if (tempEncoderCount3 != encoder3Count) {
    sendReport = true;

    if (tempEncoderCount3 > encoder3Count) {
      bleGamepad.press(BUTTON_18);
    } else {
      bleGamepad.press(BUTTON_19);
    }
  }

  if (sendReport) {
    bleGamepad.sendReport();
    delay(400);

    bleGamepad.release(BUTTON_14);
    bleGamepad.release(BUTTON_15);
    bleGamepad.release(BUTTON_16);
    bleGamepad.release(BUTTON_17);
    bleGamepad.release(BUTTON_18);
    bleGamepad.release(BUTTON_19);
    bleGamepad.sendReport();
    delay(300);

    encoder1Count = encoder1.getCount();
    encoder2Count = encoder2.getCount();
    encoder3Count = encoder3.getCount();
  }
}

void KeypadUpdate() {
  customKeypad.getKeys();

  for (int i = 0; i < LIST_MAX; i++)  // Scan the whole key list.      //LIST_MAX is provided by the Keypad library and gives the number of buttons of the Keypad instance
  {
    if (customKeypad.key[i].stateChanged)  // Only find keys that have changed state.
    {
      uint8_t keystate = customKeypad.key[i].kstate;

      if (keystate == PRESSED) {
        bleGamepad.press(customKeypad.key[i].kchar);
      }  // Press or release button based on the current state
      if (keystate == RELEASED) {
        bleGamepad.release(customKeypad.key[i].kchar);
      }

      bleGamepad.sendReport();  // Send the HID report after values for all button states are updated, and at least one button state had changed
    }
  }
}

void printWelcomeMessage() {
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setFont(NULL);
  display.println("BUTTON BOX v0.1.0");
  display.println("FW: nCNNtdTEix");
  display.display();
}

void printStandyMessage() {
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setFont(NULL);
  // display.setCursor(0, 0);
  // display.println("BUTTON BOX v0.1.0");
  // display.println("FW: nCNNtdTEix");
  display.setTextSize(2);
  printCenter("CONNECTED", 0, 20);
  display.display();
}

void printConnectingMessage() {
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setFont(NULL);
  display.setTextSize(2);
  printCenter("CONNECTING", 0, 20);
  display.display();
}

void printErrorConnection() {
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  display.setTextSize(1);
  display.setFont(NULL);
  // display.setCursor(0, 0);
  // display.println("BUTTON BOX v0.1.0");
  // display.println("FW: nCNNtdTEix");
  display.setTextSize(2);
  printCenter("ERROR", 0, 20);
  display.display();
}

void printCenter(const String buf, int x, int y) {
  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(buf, x, y, &x1, &y1, &w, &h);  //calc width of new string
  display.setCursor((x - w / 2) + (128 / 2), y);
  display.print(buf);
}
praditautama commented 1 year ago

I tried to use https://github.com/lemmingDev/ESP32-BLE-Gamepad/issues/111#issuecomment-1254260699 and it worked but connection is not stable

is it related to NimBLE?

LeeNX commented 1 year ago

I have not seen this error reported in the past, can't really give you much feedback, just options on how to possible track the problem down.

Try the simpler example code first, like SingleButton. Don't forget to remove/delete/forget the device in the host manager you using, as the UUID and other BLE attribs can be cached and might not change on the host, even if you upload new code to your ESP32 device.

Another things to look at, which version of: Arduino core for the ESP32 NimBLE-Arduino

Also, If you are able to post an example or snippet of the code showing the problem, might be easier to give more feedback.

Hope that helps.

praditautama commented 1 year ago

Hi @LeeNX I added my source code.

LeeNX commented 1 year ago

Nothing jumps out as wrong or broken.

Test the SingleButton sketch, to rule out Bluetooth hardware/OS/Drivers.

If you not using HATs, could disable them.

Interesting problem, keep us updated.

praditautama commented 1 year ago

hi @LeeNX

I bought another BT 5.x USB dongle and I don't get WDF_VIOLATION errors anymore.

I think it's UB400 USD dongle issue.

I will close this