earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.03k stars 421 forks source link

RP2040 Raspberry Pico W issues with KeyboardBLE #2547

Open nkoske opened 1 week ago

nkoske commented 1 week ago

Im having Trouble to get KeyboardBLE Running and staying Connected.

Compiling my Code and running it is no issue, but when i connect to my Win11 Laptop it connects and disconnects after few seconds. Windows 11 tells me its an driver issue, i tryed to install new drivers (other BT devices work just fine).

My gut tells me its either my code or the libs fault. What im doing wrong here?


#include <KeyboardBLE.h>

// Define keyboard inputs and outputs
byte inputs[] = {6, 7, 8}; // Minimal 3 inputs
byte outputs[] = {0, 1};   // Minimal 2 outputs

// Simple keyboard layout with a 2x3 matrix
char layout[2][3] = {
    {'a', 'b', 'c'},
    {'d', 'e', 'f'}
};

int keyDown[2][3] = {0};   // Key status

void setup() {
  // Initialize outputs
  for (int i = 0; i < 2; i++) {
    pinMode(outputs[i], OUTPUT);
    digitalWrite(outputs[i], HIGH);
  }

  // Initialize inputs
  for (int i = 0; i < 3; i++) {
    pinMode(inputs[i], INPUT_PULLUP);
  }

  // Start Bluetooth HID
  KeyboardBLE.begin();
  delay(5000);  // Allow time for Bluetooth to initialize
}

void loop() {
  for (int i = 0; i < 2; i++) {    
    digitalWrite(outputs[i], LOW);  // Set one row low

    for (int j = 0; j < 3; j++) {
      if (digitalRead(inputs[j]) == LOW) {
        keyPressed(i, j);  // Call function when key is pressed
      } else if (keyDown[i][j] != 0) {
        resetKey(i, j);    // Reset key when released
      }
    }

    digitalWrite(outputs[i], HIGH);  // Set the row back high
  }
}

void keyPressed(int row, int col) {
  if (keyDown[row][col] == 0) {
    KeyboardBLE.write(layout[row][col]);  // Send keypress
  }
  keyDown[row][col]++;
}

void resetKey(int row, int col) {
  keyDown[row][col] = 0;
  KeyboardBLE.release(layout[row][col]);  // Release the key
}
maxgerhardt commented 4 days ago

How is your Pico W board powered? Maybe by a power bank, that shuts off if not enough current is pulled after some time?

nkoske commented 4 days ago

Im Testing on a Pc Port or on a USB-PSU

maxgerhardt commented 4 days ago

Interesting, I'm replicating this error on a Pico W on Windows 10 with a much simpler sketch:

grafik

#include <Arduino.h>
#include <KeyboardBLE.h>

void setup() {
  KeyboardBLE.begin();  // Start Bluetooth HID
  delay(5000);  // Allow time for Bluetooth to initialize
}

void loop() {
  if (BOOTSEL) {
   KeyboardBLE.press('A');
  } else {
   KeyboardBLE.release('A');
  }
}

(doesn't need any external buttons, uses the BOOTSEL button itself). Let's see if the verbatim examples work..

maxgerhardt commented 4 days ago

Nope, https://github.com/earlephilhower/arduino-pico/blob/master/libraries/rp2040/examples/Bootsel/Bootsel.ino runs into the same error. Let's what the nRF Connect app says-

maxgerhardt commented 4 days ago

Mhm. nRF Conenct shows an "Incorrect data length (16 bit expected): (0x) 00" error when trying to get the Boot Keyboard Input Report.. not exactly sure what the means yet.

1729347371136

earlephilhower commented 2 days ago

Re the dump you posted, @maxgerhardt ...Boot Keyboard Input Report... may be the issue. This core does not implement the boot protocol mode of operation.

HID_Keyboard is the backend and is common for USB, BT, and BLE (since HID reports are the same for all of them). There's a bit in the HID descriptor the Pico supplies which toggles between boot and normal modes. BOOT protocol mode also only allows 1 device, not composite devices and the "keyboard" is really a composite device of a keyboards and a consumer_keys (mute, pause, volup/down keys, etc.).

There also should not be a mouse descriptor at all. There is logic to combine things allowing for, say, a keyboard and mouse to be emulated. But you should need to actually instantiate the MouseBLE to have the HID report descriptor report that.

earlephilhower commented 2 days ago

The HID descriptor is good. This is dumped from the KeyboardBLE example and decoded online as a USB HID. No mouse. present from inside the core

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x06,        // Usage (Keyboard)
0xA1, 0x01,        // Collection (Application)
0x85, 0x01,        //   Report ID (1)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0xE0,        //   Usage Minimum (0xE0)
0x29, 0xE7,        //   Usage Maximum (0xE7)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x01,        //   Logical Maximum (1)
0x95, 0x08,        //   Report Count (8)
0x75, 0x01,        //   Report Size (1)
0x81, 0x02,        //   Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x01,        //   Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x05, 0x08,        //   Usage Page (LEDs)
0x19, 0x01,        //   Usage Minimum (Num Lock)
0x29, 0x05,        //   Usage Maximum (Kana)
0x95, 0x05,        //   Report Count (5)
0x75, 0x01,        //   Report Size (1)
0x91, 0x02,        //   Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01,        //   Report Count (1)
0x75, 0x03,        //   Report Size (3)
0x91, 0x01,        //   Output (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x05, 0x07,        //   Usage Page (Kbrd/Keypad)
0x19, 0x00,        //   Usage Minimum (0x00)
0x2A, 0xFF, 0x00,  //   Usage Maximum (0xFF)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x00,  //   Logical Maximum (255)
0x95, 0x06,        //   Report Count (6)
0x75, 0x08,        //   Report Size (8)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection
0x05, 0x0C,        // Usage Page (Consumer)
0x09, 0x01,        // Usage (Consumer Control)
0xA1, 0x01,        // Collection (Application)
0x85, 0x02,        //   Report ID (2)
0x15, 0x00,        //   Logical Minimum (0)
0x26, 0xFF, 0x03,  //   Logical Maximum (1023)
0x19, 0x00,        //   Usage Minimum (Unassigned)
0x2A, 0xFF, 0x03,  //   Usage Maximum (0x03FF)
0x95, 0x01,        //   Report Count (1)
0x75, 0x10,        //   Report Size (16)
0x81, 0x00,        //   Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              // End Collection

// 92 bytes

Report ID 0 is the feature report in this BLE implementation, so the report IDs of 1 and 2 look good.

earlephilhower commented 2 days ago

Version 3.9.5 (pre 2.0 SDK) works fine with the examples I've tried for BLE. This is a BTStack change in the 2.0 SDK release.

If I build and run the example I see the correct protocol mode and no errors in the "boot keyboard input report" section.... image