adafruit / Adafruit_BluefruitLE_nRF51

Arduino library for nRF51822-based Adafruit Bluefruit LE modules
197 stars 122 forks source link

F13-24 keycode do not work #48

Open zvecr opened 5 years ago

zvecr commented 5 years ago

Raised on suggestion from -> https://forums.adafruit.com/viewtopic.php?f=57&t=142419&p=706437&hilit=f13#wrap

I've noticed when building a QMK based keyboard with a Feather 32u4 Bluefruit, that certain keycodes are failing to be sent across the Bluetooth connection.

Driving down to see if this was a hardware issue i cut as much as possible and went direct to some Arduino test code.

Having modified the default hidkeyboard with some extra logic to use AT+BLEKEYBOARDCODE to send keycodes. (I've used the hid keycodes directly advertised from the AT Commands page -> https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-services)

/**************************************************************************/
/*!
    @brief  Constantly poll for new command or response data
*/
/**************************************************************************/
void loop(void)
{
  // Display prompt
  Serial.print(F("keyboard > "));

  // Check for user input and echo it back if anything was found
  char keys[BUFSIZE+1];
  getUserInput(keys, BUFSIZE);

  bool special = strstr(keys, "f24") != 0;
  if(special)
  {
    Serial.print("\nSending special ");
    Serial.println(keys);
    delay(5000);
    /*
     * f12 0x45
     * f13 0x68
     * f24 0x73
     */
    ble.print("AT+BLEKEYBOARDCODE=00-00-00-00-00-00-00-68");
    ble.println("");
  }
  else
  {
    Serial.print("\nSending ");
    Serial.println(keys);

    ble.print("AT+BleKeyboard=");
    ble.println(keys);
  }

  if( ble.waitForOK() )
  {
    Serial.println( F("OK!") );
  }else
  {
    Serial.println( F("FAILED!") );
  }

  if(special)
  {
    ble.print("AT+BLEKEYBOARDCODE=00-00");
    ble.println("");

    if( ble.waitForOK() )
    {
      Serial.println( F("OK!") );
    }else
    {
      Serial.println( F("FAILED!") );
    }
  }
}

It seems to work fine with F12 and other "standard" keycodes, however not with F13-F24 keycodes. I get the "OK!" printed on the serial monitor but no input on the connected device. I've also tried updating the firmware to the latest 0.8.0 release but this has not fixed the issue.

fauxpark commented 4 years ago

For future reference, this is the HID report descriptor that is sent to the host:

0x05, 0x01,        // Usage Page (Generic Desktop)
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)
0x29, 0x65,        //   Usage Maximum (0x65)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0x65,        //   Logical Maximum (101)
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

0x05, 0x01,        // Usage Page (Generic Desktop Ctrls)
0x09, 0x02,        // Usage (Mouse)
0xA1, 0x01,        // Collection (Application)
0x85, 0x03,        //   Report ID (3)
0x09, 0x01,        //   Usage (Pointer)
0xA1, 0x00,        //   Collection (Physical)
0x05, 0x09,        //     Usage Page (Button)
0x19, 0x01,        //     Usage Minimum (0x01)
0x29, 0x05,        //     Usage Maximum (0x05)
0x15, 0x00,        //     Logical Minimum (0)
0x25, 0x01,        //     Logical Maximum (1)
0x95, 0x05,        //     Report Count (5)
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, 0x03,        //     Report Size (3)
0x81, 0x01,        //     Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)

0x05, 0x01,        //     Usage Page (Generic Desktop Ctrls)
0x09, 0x30,        //     Usage (X)
0x09, 0x31,        //     Usage (Y)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x95, 0x02,        //     Report Count (2)
0x75, 0x08,        //     Report Size (8)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)

0x09, 0x38,        //     Usage (Wheel)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)

0x05, 0x0C,        //     Usage Page (Consumer)
0x0A, 0x38, 0x02,  //     Usage (AC Pan)
0x15, 0x81,        //     Logical Minimum (-127)
0x25, 0x7F,        //     Logical Maximum (127)
0x95, 0x01,        //     Report Count (1)
0x75, 0x08,        //     Report Size (8)
0x81, 0x06,        //     Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
0xC0,              //   End Collection
0xC0,              // End Collection

// 169 bytes

It all looks pretty standard, but of note is that it declares the Usage Maximum of the keyboard report as 0x65, or "Keyboard Application" (the Windows context menu key). Just beyond that is F13, at 0x68. It seems that if you ask the module to send F13, it will happily do so. Nevertheless macOS appears to recognise it, despite the fact that it has not been told to expect a value that high, and thus it is technically "illegal".

I don't have a Windows or Linux machine with Bluetooth to test, but I assume one or both of them follow the descriptor more closely.

It would be great if this value was bumped up from 0x65 to 0xFF. I also see that the lock LEDs are declared - is this information collected by the firmware, and if so, how would one retrieve it?