tcoppex / mbed-ble-hid

:raising_hand: Implement Human Interface Device over Bluetooth Low Energy on a Mbed stack (Arduino nano 33 BLE).
MIT License
51 stars 16 forks source link

cannot work with 16-bit hid descriptor #7

Open threedlife opened 3 years ago

threedlife commented 3 years ago

Hi, I've tried to modified the hid_report_map in HIDGamepadService.cpp to 16-bit version as following.

// Report Map with two joysticks for Android
static uint8_t hid_report_map[] =
{
  USAGE_PAGE(1),      0x01,       // Usage Page (Generic Desktop)
  USAGE(1),           0x05,       // Usage (Game Pad)
  COLLECTION(1),      0x01,       // Collection (Application)
      // Buttons
      USAGE_PAGE(1),      0x09,       // Usage Page (Buttons)
      USAGE_MINIMUM(1),   0x01,       // Usage Minimum (1)
      USAGE_MAXIMUM(1),   0x0c,       // Usage Maximum (12)
      LOGICAL_MINIMUM(1), 0x00,       // Logical Minimum (0)
      LOGICAL_MAXIMUM(1), 0x01,       // Logical Maximum (1)
      REPORT_COUNT(1),    0x0c,       // Report Count (12)
      REPORT_SIZE(1),     0x01,       // Report Size (1)
      INPUT(1),           0x02,       // Input (Data, Variable, Absolute)
      // (padding)
      REPORT_COUNT(1),    0x01,       // Report Count (1)
      REPORT_SIZE(1),     0x04,       // Report Size (4)
      INPUT(1),           0x01,       // Input (Constant) for padding
      // joysticks
      USAGE_PAGE(1),      0x01,       // Usage Page (Generic Desktop)
      USAGE(1),           0x01,       // Usage (Pointer)
      LOGICAL_MINIMUM(2), 0x01, 0x80,       // Logical Minimum (-32767)
      LOGICAL_MAXIMUM(2), 0xFF, 0x7F,       // Logical Maximum (32767)
      REPORT_SIZE(1),     0x10,       // Report Size (16)
      REPORT_COUNT(1),    0x04,       // Report Count (4)
      COLLECTION(1),      0x00,       // Collection (Physical)
        USAGE(1),           0x30,       // Usage (X)
        USAGE(1),           0x31,       // Usage (Y)
        USAGE(1),           0x32,       // Usage (Z)
        USAGE(1),           0x35,       // Usage (Rz)
        INPUT(1),           0x02,       // Input (Data, Variable, Absolute)
    END_COLLECTION(0),              // End Collection (Physical)
  END_COLLECTION(0),              // End Collection (Application)
};

The motion function was changed to following:

void HIDGamepadService::motion(float fx, float fy, float fz, float frz) {
  uint16_t x = static_cast<int>(0x10000 + fx * 0x7fff) & 0xffff;
  uint16_t y = static_cast<int>(0x10000 + fy * 0x7fff) & 0xffff;
  uint16_t z = static_cast<int>(0x10000 + fz * 0x7fff) & 0xffff;
  uint16_t rz = static_cast<int>(0x10000 + frz * 0x7fff) & 0xffff;
  hid_input_report.x_l = (uint8_t)(x & 0x00FF);   // lower 8-bit
  hid_input_report.x_h = (uint8_t)(x>>8);   // higher 8-bit
  hid_input_report.y_l = (uint8_t)(y & 0x00FF);;
  hid_input_report.y_h = (uint8_t)(y>>8);;
  hid_input_report.z_l = (uint8_t)(z & 0x00FF);;
  hid_input_report.z_h = (uint8_t)(z>>8);;
  hid_input_report.rz_l = (uint8_t)(rz & 0x00FF);;
  hid_input_report.rz_h = (uint8_t)(rz>>8);;
}

Compilation and flashing on Arduino Nano Ble 33 was successful. On Windows it reported

This device cannot start. (Code 10) 
 Report was not byte aligned.

I googled around and found out that Mbed should support 16-bit HID (https://os.mbed.com/questions/1318/16-bit-values-for-a-joystick/). The original 8-bit version worked perfectly.

What might go wrong here? Thanks.

tcoppex commented 3 years ago

Hi @threedlife ,

Mmh I am not quite sure, it is probably linked to the _hid_inputreport structure's alignment. Have you try to comment the packing pragmas (push/pop) and add manual padding to your structure instead ?

I'll try to reproduce this when I could, thanks for the feedback.

(EDIT) Relevant links:

threedlife commented 3 years ago

Hi @threedlife ,

Mmh I am not quite sure, it is probably linked to the _hid_inputreport structure's alignment. Have you try to comment the packing pragmas (push/pop) and add manual padding to your structure instead ?

I'll try to reproduce this when I could, thanks for the feedback.

(EDIT) Relevant links:

Thanks for quick response. Tried to remove packing pragmas and came to same error. The BLE device received an onDisconnectionComplete event with disconnection reason "CONNECTION_TIMEOUT = 0x08"

tcoppex commented 3 years ago

Come to think of it I believe it's the REPORT_SIZE macro in the hid_report_map structure that should be set to 2 instead of 1.

See USBHID_Types.h for this macros definition (somewhere probably on your arduino installation directory).

threedlife commented 3 years ago

sorry for late reply as was working on some other projects.

I don't think the REPORT_SIZE was the issue as I was already setting size of LOGICAL_MINIMUM / LOGICAL_MAXIMUM to 2 (pls see my initial post).

Just noticed that the caused of disconnection is Message Integrity Check (MIC) failure raised by host controller. It appears a problem with mBed OS, see https://github.com/lancaster-university/microbit-dal/issues/61. BTW, I was able to run the same report descriptor with a FreeRTOS device without any problem. I will spend some more time to find out the problem.

Were you able to reproduce the same problem? Any thoughts are appreciated.

tcoppex commented 3 years ago

Your report descriptor works fine on my android device (and GNU / Linux), I'll have to try it on Windows though. Granted I'm on the bug-ios-pairing branch, but I hardly think it's related.

Thanks for the link.